home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / abuse / src / dev.c < prev    next >
C/C++ Source or Header  |  1996-10-10  |  100KB  |  3,659 lines

  1. #include "dev.hpp"
  2. #include "input.hpp"
  3. #include "objects.hpp"
  4. #include "id.hpp"
  5. #include "lisp.hpp"
  6. #include "light.hpp"
  7. #include "devsel.hpp"
  8. #include "dprint.hpp"
  9. #include "property.hpp"
  10. #include "pmenu.hpp"
  11. #include "filesel.hpp"
  12. #include "tools.hpp"
  13. #include "game.hpp"
  14. #include "pcxread.hpp"
  15. #include "lisp_gc.hpp"
  16. #include "demo.hpp"
  17. #include "profile.hpp"
  18. #include "sbar.hpp"
  19. #include "compiled.hpp"
  20. #include "chat.hpp"
  21. #include <ctype.h>
  22.  
  23. #define make_above_tile(x) ((x)|0x4000)
  24. extern int registered;
  25. char backw_on=0,forew_on=0,show_menu_on=0,ledit_on=0,pmenu_on=0,omenu_on=0,commandw_on=0,tbw_on=0,
  26.      searchw_on=0,small_render_on=0,interpolate_draw=0,disable_autolight=0,fps_on=0,profile_on=0,
  27.      show_names=0,fg_reversed=0,
  28.      raise_all;
  29.  
  30. char *symbol_str(char *name)
  31. {
  32.   void *sym=make_find_symbol(name);
  33.   if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
  34.     return lstring_value(symbol_value(sym));
  35.  
  36.  
  37.   // maybe english.lsp was not loaded yet, let's try to do that
  38.   int sp=current_space;
  39.   current_space=PERM_SPACE;
  40.  
  41.   
  42.   char prog[50]; 
  43.   char *cs=prog;
  44.   strcpy(prog,"(setq section 'game_section)\n");
  45.   eval(compile(cs));
  46.   strcpy(prog,"(load \"lisp/english.lsp\")\n");
  47.   cs=prog;
  48.   if (!eval(compile(cs)))
  49.   {
  50.     printf("unable to open file '%s'\n",lsf);
  51.     exit(0);
  52.   }
  53.   current_space=sp;
  54.  
  55.  
  56.   // check again to see if the symbol is there
  57.   sym=make_find_symbol(name);
  58.   if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
  59.     return lstring_value(symbol_value(sym));
  60.  
  61.  
  62.   // check to see if there is a missing symbol definition
  63.   sym=make_find_symbol("missing_sym");
  64.   if (symbol_value(sym) && item_type(symbol_value(sym))==L_STRING)
  65.     return lstring_value(symbol_value(sym));
  66.  
  67.   // last resort, return english string
  68.   return "Missing language symbol!";
  69. }
  70.  
  71.  
  72. static game_object *copy_object=NULL;
  73.  
  74. pmenu *dev_menu=NULL;
  75. jwindow *mess_win=NULL,*warn_win=NULL;
  76.  
  77. game_object *edit_object;
  78. dev_controll *dev_cont=NULL;
  79. image *small_render=NULL;
  80.  
  81. int scale_mult,scale_div,dlastx,dlasty;
  82. int last_created_type=-1;
  83. char level_file[100]="levels/level00.spe";
  84.  
  85.  
  86. class cached_image : public visual_object
  87. {
  88.   int id;
  89.   public :
  90.   cached_image(int Id) { id=Id; }
  91.   virtual void draw(image *screen, int x, int y, 
  92.             window_manager *wm, filter *f)
  93.   {
  94.     if (f)
  95.       f->put_image(screen,cash.img(id),x,y,1);
  96.     else
  97.       cash.img(id)->put_image(screen,x,y); 
  98.   }
  99.   virtual int width(window_manager *wm) { return cash.img(id)->width(); }
  100.   virtual int height(window_manager *wm) { return cash.img(id)->height(); }
  101. } ;
  102.  
  103.  
  104. #define DEV_MODES 3
  105. cached_image *dev_mode_pict[DEV_MODES];
  106.  
  107. int dev_del,dev_move, dev_char_left,dev_char_right,dev_back,dev_front,dev_ok,dev_copy,dev_brain,
  108.     dev_lights,dev_objects,dev_ai,dev_mode_icon[DEV_MODES],
  109.     dev_forward,dev_backward;
  110.  
  111. char *dev_mode_icon_names[DEV_MODES]={"pixel_mode","pick_mode", /* "fill_mode",
  112.                       "line_mode","rect_mode","bar_mode", */ "area_select"};
  113.  
  114. int dev_mode_ids[DEV_MODES]={ID_DMODE_DRAW,ID_DMODE_PICK, ID_DMODE_AREA};
  115.  
  116. int edit_mode=ID_DMODE_DRAW;
  117.  
  118.  
  119. dev_term *dev_console=NULL;
  120. int ldef_width=0,ldef_height=0,ldef_r1=1,ldef_r2=100;
  121.  
  122. void make_screen_size(int w, int h);
  123.  
  124. class amb_cont : public scroller
  125. {
  126.   public :
  127.   amb_cont(int X, int Y, ifield *Next) : scroller(X,Y,ID_NULL,100,eh->font()->height()+2,0,64,Next) 
  128.   { if (player_list) sx=player_list->ambient; }
  129.   virtual void scroll_event(int newx, image *screen, window_manager *wm)
  130.   {
  131.     screen->bar(x,y,x+l-1,y+h-1,wm->dark_color());
  132.     char st[100];
  133.     sprintf(st,"%d",newx);
  134.     wm->font()->put_string(screen,x+30,y+1,st,eh->bright_color());
  135.     if (player_list)
  136.       player_list->ambient=newx;
  137.     the_game->need_refresh();
  138.   }
  139. } ;
  140.  
  141.  
  142. int confirm_quit()
  143. {
  144.   image *ok_image=cash.img(cash.reg("art/frame.spe","dev_ok",SPEC_IMAGE,1))->copy(),
  145.         *cancel_image=cash.img(cash.reg("art/frame.spe","cancel",SPEC_IMAGE,1))->copy();
  146.  
  147.  
  148.   jwindow *quitw=eh->new_window(xres/2+40,yres/2,80,-1,
  149.               new button(WINDOW_FRAME_LEFT+10,WINDOW_FRAME_TOP+20,ID_QUIT_OK,ok_image,
  150.               new button(WINDOW_FRAME_LEFT+38,WINDOW_FRAME_TOP+20,ID_CANCEL,cancel_image,
  151.               new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,symbol_str("sure?"),NULL))),
  152.                     symbol_str("quit_title"));
  153.   eh->grab_focus(quitw);
  154.   int fin=0,quit=0;
  155.   do
  156.   {
  157.     eh->flush_screen();
  158.  
  159.     event ev;
  160.     eh->get_event(ev);
  161.     if (ev.type==EV_MESSAGE && ev.message.id==ID_QUIT_OK)
  162.       fin=quit=1;
  163.     else if (ev.type==EV_MESSAGE && ev.message.id==ID_CANCEL)
  164.       fin=1;
  165.     else if (ev.type==EV_KEY && toupper(ev.key)==toupper(*symbol_str("YES")))
  166.       fin=quit=1;
  167.     else if (ev.type==EV_KEY && toupper(ev.key)==toupper(*symbol_str("NO")))
  168.       fin=1;
  169.     if ((ev.type==EV_KEY && ev.key==JK_ESC) || ev.type==EV_CLOSE_WINDOW) fin=1;
  170.  
  171.   } while (!fin);
  172.   delete ok_image;
  173.   delete cancel_image;
  174.  
  175.   the_game->reset_keymap();
  176.  
  177.   eh->close_window(quitw);
  178.   eh->flush_screen();
  179.   return quit;
  180. }
  181.  
  182. void show_object_number (game_object *who)
  183. {
  184.   int total=0,number=0;
  185.   game_object *c;  
  186.   for (c=current_level->first_object();c;c=c->next)
  187.   {
  188.     if (c->otype==who->otype)
  189.       total++;
  190.     if (c==who) number=total;
  191.   }
  192.   char msg[100];
  193.   sprintf(msg,"%s : %d of %d",object_names[who->otype],number,total);
  194. }
  195.  
  196. void dev_controll::search_backward()
  197. { ;
  198.  
  199.  
  200. void single_render()
  201. {
  202.   // enlarge clip area
  203.   the_game->first_view->cx2=the_game->first_view->cx1+
  204.                             (the_game->first_view->cx2-the_game->first_view->cx1+1)*2;
  205.   the_game->first_view->cy2=the_game->first_view->cy1+
  206.                             (the_game->first_view->cy2-the_game->first_view->cy1+1)*2;                
  207.   delete small_render;
  208.   small_render=NULL;
  209.   small_render_on=0;
  210. }
  211.  
  212. void double_render()
  213. {
  214.   small_render_on=1;
  215.   // reduce clip area
  216.   the_game->first_view->cx2=the_game->first_view->cx1+
  217.                             (the_game->first_view->cx2-the_game->first_view->cx1+1)/2;
  218.   the_game->first_view->cy2=the_game->first_view->cy1+
  219.                             (the_game->first_view->cy2-the_game->first_view->cy1+1)/2;
  220.  
  221.   small_render=new image((the_game->first_view->cx2-the_game->first_view->cx1+1),
  222.              (the_game->first_view->cy2-the_game->first_view->cy1+1),NULL,2);
  223. }
  224.  
  225.  
  226. void dev_controll::search_forward()
  227. {
  228.   if (search_window) // if no window then we can't get the object name
  229.   {
  230.     char *name=search_window->read(ID_SEARCH_TEXT);
  231.     int type=-1;    // see if this type exsists
  232.     int i;
  233.     for (i=0;i<total_objects;i++)
  234.       if (!strcmp(object_names[i],name))
  235.         type=i;
  236.     if (type==-1)
  237.     {
  238.       char msg[60];
  239.       sprintf(msg,"Object type '%s' does not exsists!\n",name);
  240.       the_game->show_help(msg);
  241.       the_game->need_refresh();
  242.     } else
  243.     {
  244.       game_object *first,*find=NULL;      
  245.       if (!search_object || search_object->otype!=type)
  246.         first=current_level->first_object();
  247.       else
  248.         first=search_object->next;
  249.       for (;!find && first;first=first->next)
  250.         if (first->otype==type)
  251.       find=first;
  252.       int loop=0;
  253.       if (!find)
  254.       {
  255.     for (first=current_level->first_object();first && !find;first=first->next)
  256.     {
  257.       if (first->otype==type)
  258.         find=first;
  259.     }
  260.     loop=1;
  261.       }
  262.       if (find)
  263.       {
  264.         search_object=find;
  265.     show_object_number(search_object);
  266.       }
  267.       else
  268.       {
  269.     the_game->show_help("No object matching name exsist in level\n");
  270.     
  271.       }
  272.     }
  273.   }
  274. }
  275.  
  276.  
  277. long dev_controll::snap_x(long x)
  278. {
  279.   if (eh->key_pressed(JK_CTRL_L) || eh->key_pressed(JK_CTRL_R))
  280.     return x-(x%the_game->ftile_width());
  281.   else if (eh->key_pressed(JK_ALT_L) || eh->key_pressed(JK_ALT_R))
  282.     return x-(x%the_game->ftile_width())+the_game->ftile_width()/2;
  283.   else return x;  
  284. }
  285.  
  286. long dev_controll::snap_y(long y)
  287. {
  288.   if (eh->key_pressed(JK_CTRL_L) || eh->key_pressed(JK_CTRL_R))
  289.     return y-(y%the_game->ftile_height())-1;
  290.   else if (eh->key_pressed(JK_ALT_L) || eh->key_pressed(JK_ALT_R))
  291.     return y-(y%the_game->ftile_height())+the_game->ftile_height()/2-1;
  292.   else return y;
  293. }
  294.  
  295. void dev_controll::make_ambient()
  296. {
  297.   if (!ambw)
  298.   ambw=eh->new_window(prop->getd("ambient x",-1),
  299.               prop->getd("ambient y",-1),-1,-1,
  300.               new amb_cont(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,NULL),"ambient");
  301. }
  302.  
  303. void dev_term::execute(char *st)
  304. {
  305.   if (!strcmp(st,"?"))
  306.   {
  307.     put_string("unchop x y, size x y,\n"
  308.            "load, esave, name\n");
  309.   } else 
  310.   {
  311.     event ev;
  312.     dv->do_command(st,ev);
  313.   }
  314. }
  315.  
  316. void load_dev_icons()
  317. {
  318.   char *artf="art/dev.spe";
  319.   dev_del=cash.reg(artf,"dev_del",SPEC_IMAGE,0);
  320.   dev_move=cash.reg(artf,"dev_move",SPEC_IMAGE,0);
  321.   dev_char_left=cash.reg(artf,"dev_char_left",SPEC_IMAGE,0);
  322.   dev_char_right=cash.reg(artf,"dev_char_right",SPEC_IMAGE,0);
  323.   dev_back=cash.reg(artf,"dev_back",SPEC_IMAGE,0);
  324.   dev_front=cash.reg(artf,"dev_front",SPEC_IMAGE,0);
  325.   dev_ok=cash.reg(artf,"dev_ok",SPEC_IMAGE,0);
  326.   dev_copy=cash.reg(artf,"dev_copy",SPEC_IMAGE,0);
  327.   dev_brain=cash.reg(artf,"brain",SPEC_IMAGE,0);
  328.   dev_lights=cash.reg(artf,"lights",SPEC_IMAGE,0);
  329.   dev_objects=cash.reg(artf,"objects",SPEC_IMAGE,0);
  330.   dev_ai=cash.reg(artf,"ai",SPEC_IMAGE,0);
  331.   dev_forward=cash.reg(artf,"forward",SPEC_IMAGE,0);
  332.   dev_backward=cash.reg(artf,"backward",SPEC_IMAGE,0);
  333.  
  334.   for (int i=0;i<DEV_MODES;i++)
  335.     dev_mode_icon[i]=cash.reg(artf,dev_mode_icon_names[i],SPEC_IMAGE,0);
  336.   
  337. }
  338.  
  339. void scale_put(image *im, image *screen, int x, int y, short new_width, short new_height)
  340. {
  341.   unsigned char *sl1,*sl2;
  342.   long xstep=(im->width()<<16)/new_width,
  343.        ystep=(im->height()<<16)/new_height,iy,ix,sx,ix_start,iy_start;
  344.   screen->add_dirty(x,y,x+new_width-1,y+new_height-1);
  345.  
  346.  
  347.   short cx1,cy1,cx2,cy2;
  348.   screen->get_clip(cx1,cy1,cx2,cy2);
  349.   if (cx1>cx2 || cy1>cy2 || x>cx2 || y>cy2 || x+new_width<=cx1 || y+new_height<=cy1) return ;
  350.   if (x<cx1)
  351.   {
  352.     ix_start=(cx1-x)*xstep;
  353.     new_width-=(cx1-x);
  354.     x=cx1;
  355.   } else ix_start=0;
  356.   if (x+new_width>=cx2)
  357.     new_width-=x+new_width-1-cx2;
  358.   if (y<cy1)
  359.   {
  360.     iy_start=(cy1-y)*ystep;
  361.     new_height-=(cy1-y);
  362.     y=cy1;
  363.   } else iy_start=0;
  364.   if (y+new_height>cy2)
  365.     new_height-=y+new_height-cy2;
  366.   
  367.  
  368.   for (iy=iy_start;new_height>0;new_height--,y++,iy+=ystep)
  369.   {
  370.     sl1=im->scan_line(iy>>16);
  371.     sl2=screen->scan_line(y)+x;
  372.     for (ix=ix_start,sx=0;sx<new_width;sx++,ix+=xstep,sl2++)
  373.       *sl2=sl1[ix>>16];    
  374.   }
  375. }
  376.  
  377.  
  378. void scale_put_trans(image *im, image *screen, int x, int y, short new_width, short new_height)
  379. {
  380.   unsigned char *sl1,*sl2;
  381.   long xstep=(im->width()<<16)/new_width,
  382.        ystep=(im->height()<<16)/new_height,iy,ix,sx,ix_start,iy_start;
  383.   screen->add_dirty(x,y,x+new_width-1,y+new_height-1);
  384.  
  385.  
  386.   short cx1,cy1,cx2,cy2;
  387.   screen->get_clip(cx1,cy1,cx2,cy2);
  388.   if (cx1>cx2 || cy1>cy2 || x>cx2 || y>cy2 || x+new_width<=cx1 || y+new_height<=cy1) return ;
  389.   if (x<cx1)
  390.   {
  391.     ix_start=(cx1-x)*xstep;
  392.     new_width-=(cx1-x);
  393.     x=cx1;
  394.   } else ix_start=0;
  395.   if (x+new_width>=cx2)
  396.     new_width-=x+new_width-1-cx2;
  397.   if (y<cy1)
  398.   {
  399.     iy_start=(cy1-y)*ystep;
  400.     new_height-=(cy1-y);
  401.     y=cy1;
  402.   } else iy_start=0;
  403.   if (y+new_height>cy2)
  404.     new_height-=y+new_height-cy2;
  405.   
  406.   uchar d;
  407.   for (iy=iy_start;new_height>0;new_height--,y++,iy+=ystep)
  408.   {
  409.     sl1=im->scan_line(iy>>16);
  410.     sl2=screen->scan_line(y)+x;
  411.     for (ix=ix_start,sx=0;sx<new_width;sx++,ix+=xstep,sl2++)
  412.     {
  413.       d=sl1[ix>>16];
  414.       if (d)
  415.         *sl2=d;
  416.     }
  417.   }
  418. }
  419.  
  420. int dev_controll::need_plus_minus()
  421. {
  422.   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
  423. }
  424.  
  425. int dev_controll::need_arrows()
  426. {
  427.   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
  428. }
  429.  
  430. int dev_controll::repeat_key_mode()
  431. {
  432.   if (state==DEV_MOVE_LIGHT) return 1; else return 0;
  433. }
  434.  
  435. int last_link_x=0,last_link_y=0;
  436.  
  437. void dev_controll::dev_draw(view *v)
  438. {
  439.   long x1,y1,x2,y2;
  440.   if (dev&EDIT_MODE)
  441.   {
  442.     long vx=v->xoff(),vy=v->yoff();
  443.   
  444.     if (dev&DRAW_LINKS)
  445.     {
  446.       for (light_source *f=first_light_source;f;f=f->next)
  447.       {
  448.     if (f->x-vx>=0 && f->x-vx<=(v->cx2-v->cx1+1) && f->y-vy>=0 && f->y-vy<=(v->cy2-v->cy1+1))
  449.     {
  450.       image *im=cash.img(light_buttons[f->type]);
  451.       im->put_image(screen,f->x-vx+v->cx1-im->width()/2,f->y-vy+v->cy1-im->height()/2,1);
  452.       screen->rectangle(f->x1-vx+v->cx1,f->y1-vy+v->cy1,f->x2-vx+v->cx1,f->y2-vy+v->cy1,
  453.                 eh->medium_color());
  454.     }
  455.       }
  456.     }
  457.  
  458.     if (link_object)
  459.     {
  460.       long rx1,ry1;
  461.       the_game->game_to_mouse(link_object->x,link_object->y,v,rx1,ry1);      
  462.       screen->line(rx1,ry1,dlastx,dlasty,yellow);            
  463.     }
  464.  
  465.     if (selected_light)
  466.     {
  467.       image *i=cash.img(light_buttons[0]);
  468.       int l=i->width()/2,h=i->height()/2;
  469.       long rx1,ry1;
  470.       the_game->game_to_mouse(selected_light->x,selected_light->y,v,rx1,ry1);      
  471.       screen->rectangle(rx1-l,ry1-h,rx1+l,ry1+h,eh->bright_color());
  472.     }
  473.  
  474.     game_object *o;
  475.     if (show_names)
  476.       for (o=current_level->first_object();o;o=o->next)
  477.       {
  478.     the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
  479.     char *nm=object_names[o->otype];
  480.     console_font->put_string(screen,x1-strlen(nm)*console_font->width()/2,y1+2,nm);
  481.       }
  482.     
  483.     if (dev&DRAW_LINKS)
  484.     {
  485.       // draw connections between objects
  486.       for (o=current_level->first_object();o;o=o->next)
  487.       {
  488.     the_game->game_to_mouse(o->x,o->y,current_view,x1,y1);
  489.  
  490.     int i=0;
  491.     for (;i<o->total_objects();i++)
  492.     {
  493.       game_object *other=o->get_object(i);
  494.       the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);    
  495.       screen->line(x1,y1,x2,y2,eh->bright_color());
  496.     }
  497.  
  498.     for (i=0;i<o->total_lights();i++)
  499.     {
  500.       light_source *l=o->get_light(i);
  501.       the_game->game_to_mouse(l->x,l->y,current_view,x2,y2);
  502.       screen->line(x1,y1,x2,y2,light_connection_color);
  503.     }
  504.  
  505.       }
  506.     }
  507.  
  508.     if (selected_object)
  509.     {    
  510.       selected_object->picture_space(x1,y1,x2,y2);    
  511.       long rx1,ry1,rx2,ry2;
  512.       the_game->game_to_mouse(x1,y1,v,rx1,ry1);
  513.       the_game->game_to_mouse(x2,y2,v,rx2,ry2);
  514.       screen->rectangle(rx1,ry1,rx2,ry2,eh->bright_color());
  515.  
  516.       the_game->game_to_mouse(selected_object->x,selected_object->y,current_view,x1,y1);
  517.       for (int i=0;i<selected_object->total_objects();i++)
  518.       {
  519.     game_object *other=selected_object->get_object(i);
  520.     the_game->game_to_mouse(other->x,other->y,current_view,x2,y2);
  521.     screen->line(x1,y1,x2,y2,light_connection_color);
  522.       }
  523.     }  
  524.  
  525.  
  526.   }
  527.  
  528.   update_memprof();
  529. }
  530.  
  531. light_source *find_light(long x, long y)
  532. {
  533.   image *i=cash.img(light_buttons[0]);
  534.   int l=i->width()/2,h=i->height()/2;
  535.   for (light_source *f=first_light_source;f;f=f->next)
  536.   {
  537.     if (x>=f->x-l && x<=f->x+l && y>=f->y-h && y<=f->y+h)
  538.       return f;
  539.   }
  540.   return NULL;
  541. }
  542.  
  543.  
  544. extern void small_static_allocation_summary(int &total, int *&static_list, int *&cache_list);
  545.  
  546. void dev_controll::update_memprof()
  547. {
  548.   if (memprof)
  549.   {
  550.     int i,largest=0;
  551.     int total,*st,*ch;
  552.     small_static_allocation_summary(total,st,ch); 
  553.  
  554.     int x=WINDOW_FRAME_LEFT;
  555.     int y=WINDOW_FRAME_TOP;
  556.     memprof->clear();
  557.  
  558.     for (i=0;i<total;i++)
  559.     {
  560.       int h=st[i]*100/3000;  x++;
  561.       memprof->screen->bar(x,y,x,y+h,eh->bright_color());
  562.       h=ch[i]*100/3000;
  563.       memprof->screen->bar(x,y,x,y+h,eh->medium_color());
  564.       x++;
  565.     }
  566.     jfree(st);
  567.     jfree(ch);
  568.     char buf[100];
  569.     sprintf(buf,"%8d %8d",j_allocated(),j_available());
  570.     eh->font()->put_string(memprof->screen,memprof->x1(),memprof->y2()-eh->font()->height(),buf);
  571.  
  572.   }
  573.   
  574. }
  575.  
  576. void dev_controll::toggle_memprof()
  577. {
  578.   if (memprof)
  579.   {
  580.     prop->setd("memprof x",memprof->x);
  581.     prop->setd("memprof y",memprof->y);
  582.     eh->close_window(memprof);
  583.     memprof=NULL;
  584.   } else
  585.   {
  586.     int total,*st,*ch;
  587.     small_static_allocation_summary(total,st,ch);
  588.     jfree(st);
  589.     jfree(ch);
  590.     memprof=eh->new_window(0,0,total*2+20,100,NULL);
  591.     update_memprof();   
  592.   }
  593. }
  594.  
  595. void dev_controll::toggle_toolbar()
  596. {
  597.   if (tbw)
  598.   {
  599.     tbw_on=0;
  600.     prop->setd("toolbar x",tbw->x);
  601.     prop->setd("toolbar y",tbw->y);
  602.     eh->close_window(tbw);
  603.     tbw=NULL;
  604.   } else
  605.   {
  606.     tbw_on=1;
  607.     int setx=0;
  608.     for (int i=0;i<DEV_MODES;i++)
  609.     {
  610.       if (edit_mode==dev_mode_ids[i])
  611.         setx=i;
  612.       dev_mode_pict[i]=new cached_image(dev_mode_icon[i]);
  613.     }
  614.  
  615.     tool_picker *tp=new tool_picker(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP, 
  616.                          ID_NULL,
  617.                          5,(visual_object **)dev_mode_pict,dev_mode_ids,DEV_MODES,
  618.                         pal,pal,eh,NULL);
  619.     int sx=WINDOW_FRAME_LEFT,sy=WINDOW_FRAME_TOP;
  620.     tbw=eh->new_window(prop->getd("toolbar x",-1),
  621.                prop->getd("toolbar y",-1),-1,-1,tp);
  622.     tp->set_x(setx,tbw->screen,eh);
  623.   }
  624. }
  625.  
  626. void dev_controll::toggle_show_menu()
  627. {
  628.   if (show_menu)
  629.   {
  630.     show_menu_on=0;
  631.     prop->setd("layer x",show_menu->x);
  632.     prop->setd("layer y",show_menu->y);
  633.     eh->close_window(show_menu);
  634.     show_menu=NULL;
  635.   } else
  636.   {
  637.     show_menu_on=1;
  638.     int sx=WINDOW_FRAME_LEFT,sy=WINDOW_FRAME_TOP;
  639.  
  640.     button *lnb=new button(sx,sy+100,SHOW_LINKS,            symbol_str("l_links"),NULL);           if (dev&DRAW_LINKS)          lnb->push();
  641.     button *lb=new button(sx,sy+80,  SHOW_LIGHT,            symbol_str("l_light"),lnb);          if (dev&DRAW_LIGHTS)         lb->push();
  642.     button *cb=new button(sx,sy+60,  SHOW_CHARACTERS,       symbol_str("l_char"),lb);       if (dev&DRAW_PEOPLE_LAYER)   cb->push();
  643.     button *bb=new button(sx,sy+40,  SHOW_BACKGROUND,       symbol_str("l_back"),cb);       if (dev&DRAW_BG_LAYER)       bb->push();
  644.     button *bdb=new button(sx,sy+20, SHOW_FOREGROUND_BOUND, symbol_str("l_bound"),bb); if (dev&DRAW_FG_BOUND_LAYER) bdb->push();
  645.     button *fb=new button(sx,sy+ 0,  SHOW_FOREGROUND,       symbol_str("l_fore"),bdb);      if (dev&DRAW_FG_LAYER)       fb->push();
  646.  
  647.     show_menu=eh->new_window(prop->getd("layer x",-1),
  648.                  prop->getd("layer y",-1),
  649.                  -1,-1,fb,symbol_str(symbol_str("SHOW?")));
  650.   }
  651. }
  652.  
  653.  
  654. char **listable_objs=NULL;
  655. int total_listable;
  656.  
  657. void dev_controll::toggle_omenu()
  658. {
  659.   if (omenu)
  660.   {
  661.     omenu_on=0;
  662.     prop->setd("objects x",omenu->x);
  663.     prop->setd("objects y",omenu->y);
  664.     eh->close_window(omenu);
  665.     omenu=NULL;
  666.     jfree(listable_objs);
  667.     listable_objs=NULL;
  668.   }
  669.   else
  670.   {
  671.     omenu_on=1;
  672.     total_listable=0;
  673.     int i=0;
  674.     for (;i<total_objects;i++)
  675.       if (!figures[i]->get_cflag(CFLAG_UNLISTABLE))
  676.         total_listable++;
  677.     listable_objs=(char **)jmalloc(sizeof(char *)*total_listable,"omenu list");
  678.     int c=0;   
  679.     for (i=0;i<total_objects;i++)
  680.       if (!figures[i]->get_cflag(CFLAG_UNLISTABLE))
  681.       {
  682.     listable_objs[c]=object_names[i];
  683.     c++;
  684.       }
  685.           
  686.     omenu=eh->new_window(prop->getd("objects x",0),
  687.              prop->getd("objects y",0),-1,-1,
  688.              new pick_list(WINDOW_FRAME_LEFT,
  689.                        WINDOW_FRAME_TOP,DEV_CREATE,yres/eh->font()->height()/2,
  690.                        listable_objs,total_listable,0,NULL,cash.img(window_texture)));
  691.   }  
  692.  
  693. int get_omenu_item(int x)
  694. {
  695.   for (int i=0;i<total_objects;i++)
  696.     if (listable_objs[x]==object_names[i])
  697.       return i;
  698.   return 0;
  699. }
  700.  
  701. void dev_controll::toggle_pmenu()
  702. {
  703.   if (pmenu)
  704.   {
  705.     pmenu_on=0;
  706.     prop->setd("pal x",pmenu->x);
  707.     prop->setd("pal y",pmenu->y);
  708.     eh->close_window(pmenu);
  709.     pmenu=NULL;
  710.     jfree(pwin_list);
  711.   }
  712.   else if (total_pals)
  713.   {
  714.     pmenu_on=1;
  715.     pwin_list=(char **)jmalloc(total_pals*sizeof(char *),"pal pick list");
  716.     int i;
  717.     for (i=0;i<total_pals;i++)
  718.       pwin_list[i]=pal_wins[i]->name;
  719.  
  720.     pmenu=eh->new_window(prop->getd("pal x",0),
  721.              prop->getd("pal y",-1),
  722.              -1,-1,
  723.              new pick_list(WINDOW_FRAME_LEFT,
  724.                        WINDOW_FRAME_TOP,DEV_PALETTE,yres/eh->font()->height()/2,
  725.                        pwin_list,total_pals,0,NULL,cash.img(window_texture)));
  726.   } else the_game->show_help(symbol_str("no_pals"));
  727.  
  728.  
  729. void dev_controll::toggle_fgw()
  730. {
  731.   if (!forew)
  732.   {
  733.     forew_on=0;
  734.     int maxh=(yres-25)/(the_game->ftile_height()/fg_scale);
  735.     int tw=the_game->ftile_width()*fg_w/fg_scale,
  736.         th=the_game->ftile_height()/fg_scale;
  737.  
  738.     tile_picker *f_tp=new tile_picker(WINDOW_FRAME_LEFT+1,WINDOW_FRAME_TOP+1,
  739.                      DEV_FG_PICKER,SPEC_FORETILE,eh,fg_scale,maxh,fg_w,NULL);
  740.     f_tp->reverse();
  741.  
  742.     forew=eh->new_window(prop->getd("fore x",-30),
  743.              prop->getd("fore y",0),
  744.              -1,-1,
  745.              f_tp,symbol_str("l_fg"));
  746.   } else
  747.   { 
  748.     forew_on=1;
  749.     prop->setd("fore x",forew->x);
  750.     prop->setd("fore y",forew->y);
  751.     eh->close_window(forew);
  752.     forew=NULL;
  753.   }
  754. }
  755.  
  756. void dev_controll::toggle_music_window()
  757. {
  758. /*  if (!music_window)
  759.   {
  760.     music_window=eh->new_window(-1,30,0,0,
  761.              new pick_list(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,
  762.                        DEV_MUSIC_PICKLIST,10,song_list,total_songs,0,NULL));
  763.     eh->fnt->put_string(music_window->screen,WINDOW_FRAME_LEFT,1,"songs");
  764.   } else
  765.   { 
  766.     eh->close_window(music_window);
  767.     music_window=NULL;
  768.   }*/
  769. }
  770.  
  771. void dev_controll::toggle_bgw()
  772. {
  773.   if (!backw)
  774.   {
  775.     backw_on=0;
  776.     int maxh=(yres-25)/(the_game->btile_height()/bg_scale);
  777.     int tw=the_game->btile_width()*bg_w/bg_scale,
  778.         th=the_game->btile_height()/bg_scale;
  779.  
  780.     backw=eh->new_window(prop->getd("back x",-30),
  781.              prop->getd("back y",0),
  782.              -1,-1,
  783.              new tile_picker(WINDOW_FRAME_LEFT+1,WINDOW_FRAME_TOP+1,
  784.                      DEV_BG_PICKER,SPEC_BACKTILE,eh,bg_scale,maxh,bg_w,NULL),symbol_str("l_bg"));
  785.   } else
  786.   { 
  787.     backw_on=1;
  788.     prop->setd("back x",backw->x);
  789.     prop->setd("back y",backw->y);
  790.     eh->close_window(backw);
  791.     backw=NULL;
  792.   }
  793. }
  794.  
  795. void dev_controll::toggle_search_window()
  796. {
  797.   if (!search_window)
  798.   {
  799.     int wl=WINDOW_FRAME_LEFT+1,
  800.         wh=WINDOW_FRAME_TOP+1;
  801.     int bh=cash.img(dev_forward)->height(),
  802.         bw=cash.img(dev_forward)->width();
  803.     search_window=eh->new_window(prop->getd("searchw x",-30),
  804.                  prop->getd("searchw y",0),
  805.                  -1,-1,
  806.                  new text_field(wl,wh,ID_SEARCH_TEXT,"object name>",
  807.                         "***************************",
  808.                         prop->get("search name",""),
  809.                   new button(wl+bw*1,wh+eh->font()->height()+5,ID_SEARCH_BACKWARD,
  810.                         cash.img(dev_backward),
  811.                   new button(wl+bw*3,wh+eh->font()->height()+5,ID_SEARCH_FOREWARD,
  812.                         cash.img(dev_forward),NULL))),"SEARCH");
  813.     searchw_on=0;
  814.   } else
  815.   {
  816.     searchw_on=1; 
  817.     prop->setd("searchw x",search_window->x);
  818.     prop->setd("searchw y",search_window->y);
  819.     prop->set("search name",search_window->read(ID_SEARCH_TEXT));
  820.     eh->close_window(search_window);
  821.     search_window=NULL;
  822.     search_object=NULL;
  823.   }
  824. }
  825.  
  826. int open_owin=0,open_fwin=0,open_bwin=0,start_edit=0,start_nodelay=0,start_doubled=0,start_mem=0;
  827.  
  828.  
  829. int get_option(char *name);
  830.  
  831.  
  832. void dev_init(int argc, char **argv)
  833. {
  834.   scale_mult=1;
  835.   scale_div=1; 
  836.   dev=0;
  837.   int i;
  838.   prop=new property_manager;
  839.   prop->load("defaults.prp");
  840.  
  841.   for (i=1;i<argc;i++)
  842.   {    
  843.     if (!strcmp(argv[i],"-edit"))
  844.     {
  845.       if (!registered)
  846.         printf("%s\n",symbol_str("no_edit"));
  847.       else
  848.       {
  849.                 dev|=EDIT_MODE;    
  850.                 start_edit=1;
  851.                 start_running=1;
  852.                 disable_autolight=1;
  853.                 if (get_option("-2"))
  854.                 {
  855.                   printf("%s\n",symbol_str("no2"));
  856.                   exit(0);
  857.                 }
  858.       }
  859.     }
  860.     else if (!strcmp(argv[i],"-fwin"))
  861.       open_fwin=1;    
  862.     else if (!strcmp(argv[i],"-show_mem"))
  863.       start_mem=1;    
  864.     else if (!strcmp(argv[i],"-bwin"))
  865.       open_bwin=1;          
  866.     else if (!strcmp(argv[i],"-owin"))
  867.       open_owin=1;        
  868.     else if (!strcmp(argv[i],"-nodelay"))
  869.       start_nodelay=1;        
  870.     else if (!strcmp(argv[i],"-scale"))
  871.     {
  872.       i++;      
  873.       scale_mult=atoi(argv[i++]);
  874.       scale_div=atoi(argv[i]);
  875.     } else if (!strcmp(argv[i],"-f"))
  876.     {
  877.       i++;
  878.       strcpy(level_file,argv[i]);
  879.     } else if (!strcmp(argv[i],"-2"))
  880.       start_doubled=1;
  881.     else if (!strcmp(argv[i],"-demo"))
  882.       demo_start=1;
  883.  
  884.   }  
  885.  
  886.   if (get_option("-no_autolight"))
  887.     disable_autolight=0;
  888.  
  889.   if ((get_option("-size") || get_option("-vmode")) && !start_edit)
  890.   {
  891.     printf("%s\n",symbol_str("no_hirez"));
  892.     exit(0);
  893.   }
  894.  
  895.   fg_reversed=prop->getd("fg_reversed",0);
  896.   mouse_scrolling=prop->getd("mouse_scrolling",0);
  897.   palettes_locked=prop->getd("palettes_locked",0);
  898.   view_shift_disabled=prop->getd("view_shift_disabled",0);
  899.   fps_on=prop->getd("fps_on",0);
  900.   show_names=prop->getd("show_names",0);
  901.   raise_all=prop->getd("raise_all",0);
  902. }
  903.  
  904. static pmenu *make_menu(int x, int y);
  905.  
  906.  
  907. dev_controll::dev_controll()
  908. {
  909.   area_win=NULL;
  910.   current_area=NULL;
  911.   fg_w=bg_w=1;
  912.   commandw=NULL;
  913.   bg_scale=fg_scale=1;
  914.   pal_wins=NULL;
  915.   total_pals=0;
  916.   state=DEV_SELECT;
  917.   aiw=NULL;
  918.   edit_light=NULL;
  919.   selected_light=NULL;
  920.  
  921.   tbw=NULL;
  922.   modew=NULL;
  923.   link_object=NULL;
  924.   selected_object=NULL;
  925.   edit_object=NULL;
  926.   ai_object=NULL;
  927.   memprof=NULL;
  928.   oedit=NULL;  
  929.   forew=NULL;
  930.   backw=NULL;  
  931.   omenu=NULL;  
  932.   ledit=NULL;
  933.   pmenu=NULL;
  934.   lightw=NULL;
  935.   search_window=NULL;
  936.   show_menu=NULL;
  937.   music_window=NULL;
  938.   ambw=NULL;
  939.   load_dev_icons();
  940.  
  941.   if (open_owin) toggle_omenu();
  942.   if (open_fwin) toggle_fgw();
  943.   if (open_bwin) toggle_bgw();
  944.   if (start_nodelay) the_game->toggle_delay();
  945.   yellow=pal->find_closest(255,255,0);
  946.   if (start_edit)
  947.   {
  948.     the_game->load_level(level_file);
  949.     the_game->draw();
  950.   }
  951.   
  952.   dev_console=new dev_term(50,18,this);
  953.   if (start_edit)
  954.     dev_menu=make_menu(0,yres-eh->font()->height()-5);    
  955.  
  956.   if (get_option("-nolight"))
  957.     dev=dev^DRAW_LIGHTS;
  958.   if (start_mem)
  959.     toggle_memprof();
  960. }
  961.  
  962.  
  963. void dev_controll::set_state(int new_state)
  964. {
  965.   if (start_doubled && new_state==RUN_STATE && !small_render)
  966.     double_render();
  967. }
  968.  
  969. void dev_controll::load_stuff()
  970. {  
  971.   if (dev & EDIT_MODE)
  972.   {
  973.     char prog[100],*cs;
  974.     strcpy(prog,"(compile-file \"edit.lsp\")");
  975.     cs=prog;
  976.     void *p=compile(cs);
  977.     l_user_stack.push(p);
  978.     eval(p);
  979.     l_user_stack.pop(1);
  980.     for (int i=0;i<total_pals;i++)
  981.       pal_wins[i]->close_window();
  982.   }
  983.  
  984. }
  985.  
  986. void dev_controll::do_command(char *command, event &ev)
  987. {
  988.   char fword[50],*st;
  989.   int l,h,x,y,i;
  990.   if (command[0]=='(')            // is this a lisp command?
  991.   {
  992.     eval(compile(command));  
  993.     return ;
  994.   }
  995.  
  996.   sscanf(command,"%s",fword);
  997.   for (st=command;*st && *st!=' ';st++);
  998.   if (*st) st++;
  999.   if (!strcmp(fword,"active"))
  1000.   {
  1001.     if (current_level && current_level->first_active_object())
  1002.     {
  1003.       game_object *o=current_level->first_active_object();
  1004.       while (o)
  1005.       {
  1006.     dprintf("%s %d %d %d %d\n",object_names[o->otype],o->x,o->y,
  1007.         figures[o->otype]->rangex,
  1008.         figures[o->otype]->rangey
  1009.         );
  1010.     o=o->next_active;
  1011.       }
  1012.     }
  1013.   }
  1014.  
  1015.   if (!strcmp(fword,"clear_weapons"))
  1016.   {
  1017.     view *f=NULL;
  1018.     for (f=player_list;f;f=f->next)
  1019.     {
  1020.       int i;
  1021.       for (i=0;i<total_weapons;i++)
  1022.     f->weapons[i]=-1;
  1023.  
  1024.       if (total_weapons)
  1025.         f->weapons[0]=0;
  1026.     }
  1027.   }
  1028.  
  1029.   if (!strcmp(fword,"reload"))
  1030.   {
  1031.     if (current_level && player_list && player_list->focus)
  1032.     {
  1033.       edit_object=selected_object=NULL;
  1034.       long cx=player_list->focus->x,cy=player_list->focus->y;
  1035.  
  1036.       // save the old weapon array
  1037.       long *w=(long *)jmalloc(total_weapons*sizeof(long),"tmp weapon array");
  1038.       memcpy(w,player_list->weapons,total_weapons*sizeof(long));
  1039.       
  1040.       char tmp[100];
  1041.       strcpy(tmp,current_level->name());
  1042.       the_game->load_level(tmp);
  1043.       current_level->unactivate_all();
  1044.  
  1045.       if (screen)  // don't draw if graphics haven't been setup yet.
  1046.         the_game->draw();
  1047.       player_list->reset_player();
  1048.       player_list->focus->x=cx;
  1049.       player_list->focus->y=cy;
  1050.  
  1051.       memcpy(player_list->weapons,w,total_weapons*sizeof(long));     
  1052.       jfree(w);
  1053.  
  1054.       the_game->need_refresh();
  1055.     }    
  1056.   }
  1057.  
  1058.   if (!strcmp(fword,"unchop"))
  1059.   {
  1060.     long rx,ry;
  1061.     the_game->btile_on(dlastx,dlasty,rx,ry);
  1062.     if (rx>=0 && ry>=0)
  1063.     {
  1064.       if (sscanf(command,"%s%d%d",fword,&l,&h)==3)
  1065.       {
  1066.     dprintf("unchopped %dx%d to ",l,h);
  1067.     l=(l+the_game->btile_width()-1)/the_game->btile_width();
  1068.     h=(h+the_game->btile_height()-1)/the_game->btile_height();
  1069.     for (y=0,i=cur_bg;y<h;y++)
  1070.           for (x=0;x<l;x++)
  1071.             the_game->put_bg(rx+x,ry+y,i++); 
  1072.     dprintf("%dx%d\n",l,h);
  1073.       } else dprintf(symbol_str("unchop1"));
  1074.  
  1075.     }      
  1076.   } 
  1077.   if (!strcmp(fword,"center"))
  1078.   {
  1079.     view *v=the_game->first_view;
  1080.     for (;v;v=v->next)
  1081.     {
  1082.       v->pan_x=0;
  1083.       v->pan_y=0;
  1084.     }
  1085.     the_game->need_refresh();
  1086.   }
  1087.  
  1088.   if (!strcmp(fword,"size"))
  1089.   {
  1090.     int l,w;    
  1091.     if (sscanf(command,"%s%d%d",fword,&l,&w)==3)
  1092.     {
  1093.       current_level->set_size(l,w);    
  1094.       dprintf("level is now %dx%d\n",l,w);
  1095.     } else dprintf(symbol_str("size1"));
  1096.  
  1097.  
  1098.   }
  1099.   if (!strcmp(fword,"name"))
  1100.   {
  1101.     while (*command && *command!=' ') command++;
  1102.     if (*command)
  1103.       current_level->set_name(command+1);    
  1104.     dprintf(symbol_str("name_now"),current_level->name());
  1105.   }
  1106.   if (!strcmp(fword,"set_first_level"))
  1107.   {
  1108.     strcpy(level_file,st);
  1109.     dprintf("first level will be '%s'\n",level_file);       
  1110.   }
  1111.  
  1112.   if (!strcmp(fword,"load"))
  1113.   {
  1114.     if (!strcmp(st,"STARTING_LEVEL"))
  1115.       st=level_file;
  1116.  
  1117.     dprintf("loading '%s'\n",st);
  1118.     the_game->load_level(st);    
  1119.     current_level->unactivate_all();
  1120.  
  1121.     the_game->need_refresh();
  1122.   }
  1123.  
  1124.   if (!strcmp(fword,"mem"))
  1125.   {
  1126.     if (st[0])    
  1127.       show_char_mem(st);
  1128.     else show_mem();
  1129.   }
  1130.  
  1131.   if (!strcmp(fword,"esave"))
  1132.   {
  1133.     dprintf(symbol_str("esave"));
  1134.     save();
  1135.   }
  1136.  
  1137.   if (!strcmp(fword,"delete"))
  1138.   {      
  1139.     if (selected_object)
  1140.     {
  1141.       if (!(dev&EDIT_MODE) && current_level->is_attacker(selected_object))
  1142.         the_game->show_help(symbol_str("nd_player"));
  1143.       else
  1144.       {      
  1145.     if (selected_object->controller())
  1146.       the_game->show_help(symbol_str("nd_player"));
  1147.     else
  1148.     {
  1149.       current_level->delete_object(selected_object);
  1150.       if (S_DELETE_SND>0) cash.sfx(S_DELETE_SND)->play(sfx_volume/2);
  1151.       selected_object=NULL;    
  1152.     }
  1153.       }
  1154.     } else if (selected_light)
  1155.     {
  1156.       if (!edit_light)
  1157.       {
  1158.     if (current_level)
  1159.     {
  1160.           current_level->remove_light(selected_light);
  1161.       if (S_DELETE_SND>0) cash.sfx(S_DELETE_SND)->play(sfx_volume/2);
  1162.     }
  1163.     else
  1164.           delete_light(selected_light);
  1165.     selected_light=NULL;
  1166.       }      
  1167.     } else the_game->show_help(symbol_str("d_nosel"));
  1168.     the_game->need_refresh();
  1169.   }
  1170.  
  1171.   if (!strcmp(fword,"create"))
  1172.   {
  1173.     char oname[100];
  1174.     sscanf(command,"%s%s",fword,oname);       // read the type of object to create
  1175.     int x,t=-1;
  1176.     for (x=0;x<total_objects;x++)             // find the object type by name
  1177.        if (!strcmp(object_names[x],oname))
  1178.          t=x;
  1179.  
  1180.     if (t>=0)                                 // did we find it?
  1181.     {
  1182.       long rx,ry;
  1183.       the_game->mouse_to_game(dlastx,dlasty,rx,ry);
  1184.       edit_object=create(t,rx,ry);
  1185.       current_level->add_object(edit_object);
  1186.       the_game->need_refresh();
  1187.       last_created_type=t;
  1188.     } else
  1189.     {
  1190.       sprintf(fword,"No such object type : %s\n",oname);
  1191.       the_game->show_help(fword);
  1192.     }
  1193.   }
  1194.  
  1195.   if (!strcmp(fword,"move"))
  1196.   {
  1197.     if (selected_object)   
  1198.       edit_object=selected_object;      
  1199.  
  1200.     if (edit_object)
  1201.       state=DEV_MOVE_OBJECT;
  1202.     else the_game->show_help("No object selected");
  1203.       
  1204.   }
  1205.   if (!strcmp(fword,"move_light"))
  1206.   {
  1207.     if (selected_light)   
  1208.       edit_light=selected_light;      
  1209.  
  1210.     if (edit_light)
  1211.       state=DEV_MOVE_LIGHT;
  1212.     else the_game->show_help("No light selected");
  1213.       
  1214.   }
  1215.  
  1216.   
  1217.   if (!strcmp(fword,"clear_auto"))
  1218.   {
  1219.     long i,j;
  1220.     for (i=0;i<current_level->foreground_width();i++)
  1221.       for (j=0;j<current_level->foreground_height();j++)
  1222.         current_level->clear_fg(i,j);
  1223.   }
  1224.  
  1225.   if (!strcmp(fword,"fg_select"))
  1226.   {
  1227.     long x,y;
  1228.     the_game->ftile_on(dlastx,dlasty,x,y);
  1229.     if (x>=0 && y>=0 && x<current_level->foreground_width() &&
  1230.     y<current_level->foreground_height())
  1231.     {
  1232.       cur_fg=current_level->get_fg(x,y);
  1233.       if (forew)      
  1234.     ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen,eh);      
  1235.       the_game->need_refresh();
  1236.     }
  1237.   }
  1238.  
  1239.   if (!strcmp(fword,"toggle_fg_raise"))
  1240.   {
  1241.     long x,y;
  1242.     the_game->ftile_on(dlastx,dlasty,x,y);
  1243.     if (x>=0 && y>=0 && x<current_level->foreground_width() &&
  1244.     y<current_level->foreground_height())    
  1245.       current_level->fg_set_raised(x,y,!current_level->fg_raised(x,y));    
  1246.   }
  1247.   
  1248.   if (!strcmp(fword,"fg_add"))
  1249.   {
  1250.     int x;
  1251.     if (sscanf(st,"%d",&x))
  1252.     {
  1253.       cur_fg++;
  1254.       if (cur_fg<0) cur_fg=0;
  1255.       if (cur_fg>=nforetiles) cur_fg=nforetiles-1;
  1256.  
  1257.       if (forew)      
  1258.     ((tile_picker *)forew->read(DEV_FG_PICKER))->recenter(forew->screen,eh);      
  1259.     }   
  1260.   }
  1261.  
  1262.   if (!strcmp(fword,"mem_report"))
  1263.     mem_report("memory.report");
  1264.  
  1265.   if (!strcmp(fword,"restart"))
  1266.   {
  1267.     current_level->restart();
  1268.   }
  1269.   if (!strcmp(fword,"quit"))
  1270.   {
  1271.     the_game->end_session();
  1272.   }
  1273.  
  1274.   if (!strcmp(fword,"to_front"))
  1275.   {
  1276.     game_object *which=selected_object;
  1277.     if (!selected_object) which=edit_object;
  1278.     if (which)    
  1279.       current_level->to_front(which);
  1280.     else the_game->show_help(symbol_str("forward?"));
  1281.   }
  1282.  
  1283.   if (!strcmp(fword,"to_back"))
  1284.   {
  1285.     game_object *which=selected_object;
  1286.     if (!selected_object) which=edit_object;
  1287.     if (which)    
  1288.       current_level->to_back(which);
  1289.     else the_game->show_help(symbol_str("back?")); 
  1290.   }
  1291.  
  1292.   if (!strcmp(fword,"set_aitype"))
  1293.   {
  1294.     game_object *which=selected_object;
  1295.     if (!selected_object) which=edit_object;
  1296.     if (which)    
  1297.     {
  1298.       int x;
  1299.       if (*st && sscanf(st,"%d",&x)!=EOF)
  1300.         which->change_aitype(x);
  1301.       else 
  1302.       {
  1303.     switch (ev.key)
  1304.     {
  1305.       case '0' : which->change_aitype(0); break;
  1306.       case '1' : which->change_aitype(1); break;
  1307.       case '2' : which->change_aitype(2); break;
  1308.       case '3' : which->change_aitype(3); break;
  1309.       case '4' : which->change_aitype(4); break;
  1310.       case '5' : which->change_aitype(5); break;
  1311.       case '6' : which->change_aitype(6); break;
  1312.       case '7' : which->change_aitype(7); break;
  1313.       case '8' : which->change_aitype(8); break;
  1314.       case '9' : which->change_aitype(9); break;
  1315.       case ')' : which->change_aitype(10); break;
  1316.       case '!' : which->change_aitype(11); break;
  1317.       case '@' : which->change_aitype(12); break;
  1318.       case '#' : which->change_aitype(13); break;
  1319.       case '$' : which->change_aitype(14); break;
  1320.       case '%' : which->change_aitype(15); break;
  1321.       case '^' : which->change_aitype(16); break;
  1322.       case '&' : which->change_aitype(17); break;
  1323.       case '*' : which->change_aitype(18); break;
  1324.       case '(' : which->change_aitype(19); break;
  1325.     }
  1326.       }     
  1327.       the_game->need_refresh();
  1328.     }
  1329.     else the_game->show_help(symbol_str("aitype"));
  1330.   }
  1331.  
  1332.  
  1333. }
  1334.  
  1335.  
  1336. void dev_controll::toggle_light_window()
  1337. {
  1338.   if (!lightw)
  1339.   {
  1340.     int wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,bh=16+6,bw=20+6,th=eh->font()->height()+4;    
  1341.     lightw=eh->new_window(prop->getd("light create x",0),
  1342.               prop->getd("light create y",0),
  1343.               -1,-1,new button_box(wl,wh,DEV_LIGHT_BUTTON_BOX,1,
  1344.                     new button(wl+bw*0,wh+bh*0,DEV_LIGHT0,cash.img(light_buttons[0]),
  1345.                     new button(wl+bw*1,wh+bh*0,DEV_LIGHT1,cash.img(light_buttons[1]),
  1346.                     new button(wl+bw*2,wh+bh*0,DEV_LIGHT2,cash.img(light_buttons[2]),
  1347.  
  1348.                     new button(wl+bw*0,wh+bh*1,DEV_LIGHT3,cash.img(light_buttons[3]),
  1349.                     new button(wl+bw*1,wh+bh*1,DEV_LIGHT4,cash.img(light_buttons[4]),
  1350.                     new button(wl+bw*2,wh+bh*1,DEV_LIGHT5,cash.img(light_buttons[5]),
  1351.  
  1352.                     new button(wl+bw*0,wh+bh*2,DEV_LIGHT6,cash.img(light_buttons[6]),
  1353.                     new button(wl+bw*1,wh+bh*2,DEV_LIGHT7,cash.img(light_buttons[7]),
  1354.                     new button(wl+bw*2,wh+bh*2,DEV_LIGHT8,cash.img(light_buttons[8]),
  1355.  
  1356.                     new button(wl+bw*0,wh+bh*3,DEV_LIGHT9,cash.img(light_buttons[9]),
  1357.                  new button(wl+bw*1,wh+bh*3,DEV_AMBIENT,cash.img(light_buttons[11]),
  1358.                            NULL))))))))))),
  1359.  
  1360.                     new text_field(wl,wh+bh*4,DEV_LIGHTW,      "W ","******",
  1361.                            prop->getd("light create w",0),
  1362.                     new text_field(wl,wh+bh*4+th*1,DEV_LIGHTH, "H ","******",
  1363.                            prop->getd("light create h",0),
  1364.                     new text_field(wl,wh+bh*4+th*2,DEV_LIGHTR1,"R1","******",
  1365.                            prop->getd("light create r1",1),
  1366.                     new text_field(wl,wh+bh*4+th*3,DEV_LIGHTR2,"R2","******",
  1367.                            prop->getd("light create r2",100),
  1368.                            NULL))))),
  1369.                                        symbol_str("l_light"));
  1370.                            
  1371.   } else
  1372.   {
  1373.     prop->setd("light create x",lightw->x);
  1374.     prop->setd("light create y",lightw->y);
  1375.     prop->setd("light create w",atoi(lightw->read(DEV_LIGHTW)));
  1376.     prop->setd("light create h",atoi(lightw->read(DEV_LIGHTH)));
  1377.     prop->setd("light create r1",atoi(lightw->read(DEV_LIGHTR1)));
  1378.     prop->setd("light create r2",atoi(lightw->read(DEV_LIGHTR2)));
  1379.     eh->close_window(lightw);
  1380.     lightw=NULL;
  1381.   }
  1382. }
  1383.  
  1384. void dev_controll::make_ai_window(game_object *o)
  1385. {
  1386.   ai_object=o;
  1387.   int th=eh->font()->height()+4,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP+20;
  1388.   if (figures[o->otype]->total_fields)
  1389.   {
  1390.     ifield *next=NULL;
  1391.     int maxl=0;
  1392.     int i=0;
  1393.     for (;i<figures[o->otype]->total_fields;i++)
  1394.       if (strlen(figures[o->otype]->fields[i]->descript_name)>maxl)
  1395.         maxl=strlen(figures[o->otype]->fields[i]->descript_name);
  1396.   
  1397.     int owh=wh;
  1398.     ifield *first,*last=NULL;
  1399.     for (i=0;i<figures[o->otype]->total_fields;i++)
  1400.     {
  1401.       char tmp[200];
  1402.       strcpy(tmp,figures[o->otype]->fields[i]->descript_name);
  1403.       for (int j=maxl-strlen(figures[o->otype]->fields[i]->descript_name);j;j--)
  1404.         strcat(tmp," ");      
  1405.       int er;
  1406.       ifield *p=new text_field(wl,wh,ID_NULL,tmp,"######",
  1407.                    (double)o->get_var_by_name(figures[o->otype]->fields[i]->real_name,er),
  1408.                    NULL);
  1409.       if (last)
  1410.         last->next=p;
  1411.       else
  1412.         first=p;
  1413.       last=p;
  1414.       wh+=th;
  1415.     }         
  1416.     aiw=eh->new_window(prop->getd("ai x",0),
  1417.                prop->getd("ai y",0),
  1418.                -1,-1,             
  1419.        new button(wl,owh-20,DEV_AI_OK,cash.img(dev_ok),first),"ai");
  1420.  
  1421.   }
  1422.   else
  1423.   {
  1424.     aiw=eh->new_window(prop->getd("ai x",0),
  1425.                prop->getd("ai y",0),
  1426.                -1,-1,
  1427.        new button(wl,wh-20,DEV_AI_OK,cash.img(dev_ok),
  1428.        new text_field(wl,wh+th*0, DEV_AI_XVEL,    symbol_str("ai_xvel"),"#####",(double)o->xvel(),
  1429.        new text_field(wl,wh+th*1, DEV_AI_YVEL,    symbol_str("ai_yvel"),"#####",(double)o->yvel(),
  1430.        new text_field(wl,wh+th*2, DEV_AI_XACEL,   symbol_str("ai_xacel"),"#####",(double)o->xacel(),
  1431.        new text_field(wl,wh+th*3, DEV_AI_YACEL,   symbol_str("ai_yacel"),"#####",(double)o->yacel(),
  1432.        new text_field(wl,wh+th*4, DEV_AI_STTIME,  symbol_str("ai_stime"),"####",(double)o->aistate_time(),
  1433.        new text_field(wl,wh+th*5, DEV_AI_GRAVITY, symbol_str("ai_gravity"),"####",(double)o->gravity(),
  1434.        new text_field(wl,wh+th*6, DEV_AI_HEALTH,  symbol_str("ai_health"),"####",(double)o->hp(),
  1435.        new text_field(wl,wh+th*7, DEV_AI_MORPHPR, symbol_str("ai_morph"),"####",(double)o->mp(),
  1436.        new text_field(wl,wh+th*8, DEV_AI_TYPE,    symbol_str("ai_type"),"####",(double)o->aitype(),
  1437.        new text_field(wl,wh+th*9,DEV_AI_STATE,    symbol_str("ai_state"),"####",(double)o->aistate(),
  1438.        new text_field(wl,wh+th*10,DEV_AI_FADE,    symbol_str("ai_fade"),"####",(double)o->fade_count(),
  1439.               NULL)))))))))))),"ai");
  1440.   }
  1441.  
  1442.   eh->grab_focus(aiw);
  1443. }
  1444.  
  1445. void dev_controll::notify_deleted_light(light_source *l)
  1446. {
  1447.   if (l==edit_light)
  1448.   {
  1449.     if (ledit)
  1450.     {
  1451.       prop->setd("ledit x",ledit->x);
  1452.       prop->setd("ledit y",ledit->y);
  1453.       eh->close_window(ledit); ledit=NULL;
  1454.     }
  1455.     edit_light=NULL;
  1456.   }
  1457.   if (l==selected_light)  
  1458.     selected_light=NULL;
  1459. }
  1460.  
  1461. void dev_controll::notify_deleted_object(game_object *o)
  1462. {
  1463.   if (o==edit_object)
  1464.   {
  1465.     state=DEV_SELECT;
  1466.     close_oedit_window();
  1467.   }
  1468.  
  1469.   if (o==ai_object)
  1470.     close_ai_window();
  1471.   if (o==search_object)
  1472.   { if (search_window)
  1473.       toggle_search_window();
  1474.     search_object=NULL;
  1475.   }
  1476.   if (o==link_object)
  1477.     link_object=NULL;
  1478.   if (o==selected_object)
  1479.   {
  1480.     selected_object=NULL;
  1481.     state=DEV_SELECT;
  1482.   }
  1483.  
  1484. }
  1485.  
  1486. void dev_controll::close_ai_window()
  1487. {
  1488.   if (aiw)
  1489.   {    
  1490.     game_object *o=ai_object;
  1491.     long x;
  1492.     if (o)
  1493.     {
  1494.       if (figures[o->otype]->total_fields)
  1495.       {
  1496.     ifield *f=aiw->inm->get(DEV_AI_OK)->next;
  1497.     for (int i=0;i<figures[o->otype]->total_fields;i++)
  1498.     {
  1499.       x=atoi(f->read());
  1500.       char *v=figures[o->otype]->fields[i]->real_name;
  1501.       int er;
  1502.       if (o->get_var_by_name(v,er)!=x)
  1503.       o->set_var_by_name(v,x);
  1504.       f=f->next;
  1505.     }
  1506.       }
  1507.       else
  1508.       {
  1509.     x=atoi(aiw->read(DEV_AI_XVEL)); if (x!=o->xvel()) o->set_xvel(x);
  1510.     x=atoi(aiw->read(DEV_AI_YVEL)); if (x!=o->yvel()) o->set_yvel(x);
  1511.  
  1512.     x=atoi(aiw->read(DEV_AI_XACEL)); if (x!=o->xacel()) o->set_xacel(x);
  1513.     x=atoi(aiw->read(DEV_AI_YACEL)); if (x!=o->yacel()) o->set_yacel(x);
  1514.  
  1515.     x=atoi(aiw->read(DEV_AI_STTIME)); if (x!=o->aistate_time()) o->set_aistate_time(x);
  1516.     x=atoi(aiw->read(DEV_AI_GRAVITY)); if (x!=o->gravity()) o->set_gravity(x);
  1517.  
  1518.     x=atoi(aiw->read(DEV_AI_HEALTH)); if (x!=o->hp()) o->set_hp(x);
  1519.     x=atoi(aiw->read(DEV_AI_MORPHPR)); if (x!=o->mp()) o->set_mp(x);
  1520.  
  1521.     x=atoi(aiw->read(DEV_AI_TYPE)); if (x!=o->aitype()) o->set_aitype(x);
  1522.     x=atoi(aiw->read(DEV_AI_STATE)); if (x!=o->aistate()) o->set_aistate(x);
  1523.     x=atoi(aiw->read(DEV_AI_FADE)); if (x!=o->fade_count()) o->set_fade_count(x);
  1524.       }
  1525.     }
  1526.     prop->setd("ai x",aiw->x);
  1527.     prop->setd("ai y",aiw->y);
  1528.     eh->close_window(aiw);
  1529.     aiw=NULL;
  1530.     ai_object=NULL;
  1531.     the_game->need_refresh();
  1532.   }
  1533. }
  1534.  
  1535.  
  1536. void dev_controll::area_handle_input(event &ev)
  1537. {
  1538.  
  1539.   if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
  1540.   {
  1541.     long gx,gy;
  1542.     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
  1543.     if (!current_level) return ;
  1544.     current_area=current_level->area_list=new area_controller(gx,gy,
  1545.                                   the_game->ftile_width(),
  1546.                                   the_game->ftile_height(),
  1547.                                   current_level->area_list); 
  1548.     the_game->need_refresh();
  1549.     state=DEV_DRAG_AREA_BOTTOM;
  1550.   }
  1551. }
  1552.  
  1553. void dev_controll::close_area_win(int read_values)
  1554. {
  1555.   if (area_win)
  1556.   {
  1557.     prop->setd("area_box x",area_win->x);
  1558.     prop->setd("area_box y",area_win->y);
  1559.  
  1560.     if (current_area && read_values)
  1561.     {      
  1562.       current_area->ambient=atoi(area_win->read(DEV_AREA_AMBIENT));
  1563.       current_area->ambient_speed=atoi(area_win->read(DEV_AREA_AMBIENT_SPEED));
  1564.       current_area->view_xoff=atoi(area_win->read(DEV_AREA_VIEW_XOFF));
  1565.       current_area->view_yoff=atoi(area_win->read(DEV_AREA_VIEW_YOFF));
  1566.       current_area->view_xoff_speed=atoi(area_win->read(DEV_AREA_VIEW_XOFF_SPEED));
  1567.       current_area->view_yoff_speed=atoi(area_win->read(DEV_AREA_VIEW_YOFF_SPEED));
  1568.     }    
  1569.     eh->close_window(area_win);
  1570.     area_win=NULL;
  1571.   }
  1572. }
  1573.  
  1574. void dev_controll::pick_handle_input(event &ev)
  1575. {
  1576.   area_controller *find=NULL;
  1577.   int find_top=0;
  1578.   if (!current_level) return;
  1579.   if (ev.type==EV_MOUSE_BUTTON && ev.mouse_button)
  1580.   {
  1581.     long mx=last_demo_mx,my=last_demo_my;
  1582.     view *v=the_game->view_in(mx,my);
  1583.     for (area_controller *a=current_level->area_list;a;a=a->next)
  1584.     {
  1585.       long x1,y1,x2,y2;
  1586.       the_game->game_to_mouse(a->x,a->y,v,x1,y1);
  1587.       the_game->game_to_mouse(a->x+a->w,a->y+a->h,v,x2,y2);
  1588.       if (abs(x1-mx)<2 && abs(y1-my)<2)
  1589.       { find=a;    find_top=1; }
  1590.       else if (abs(x2-mx)<2 && abs(y2-my)<2)
  1591.       { find=a;    find_top=0; }
  1592.     }  
  1593.  
  1594.     time_marker now;
  1595.     int dc=now.diff_time(&last_area_click)<0.5;
  1596.     last_area_click.get_time();
  1597.     if (find && current_area && dc)
  1598.     {         
  1599.       if (area_win) close_area_win(0);
  1600.       int wl=WINDOW_FRAME_LEFT;
  1601.       int wh=WINDOW_FRAME_TOP,th=eh->font()->height()+12,bw=cash.img(dev_ok)->width()+10;
  1602.       area_win=eh->new_window(prop->getd("area_box x",0),
  1603.                   prop->getd("area_box y",0),
  1604.                   -1,-1,
  1605.  
  1606.                   new button(wl+bw*0,wh-8,DEV_AREA_OK,cash.img(dev_ok),
  1607.                   new button(wl+bw*1,wh-8,DEV_AREA_DELETE,cash.img(dev_del), 
  1608.  
  1609.                   new text_field(wl,wh+th*1,DEV_AREA_AMBIENT,         symbol_str("a_ambient"),"******",current_area->ambient,
  1610.                               new text_field(wl,wh+th*2,DEV_AREA_AMBIENT_SPEED,   symbol_str("a_aspeed"),"******",current_area->ambient_speed,
  1611.                               new text_field(wl,wh+th*3,DEV_AREA_VIEW_XOFF,       symbol_str("a_view_xoff"),"******",current_area->view_xoff,
  1612.                               new text_field(wl,wh+th*4,DEV_AREA_VIEW_YOFF,       symbol_str("a_view_yoff"),"******",current_area->view_yoff,
  1613.                               new text_field(wl,wh+th*5,DEV_AREA_VIEW_XOFF_SPEED, symbol_str("a_view_xspd"),"******",current_area->view_xoff_speed,
  1614.                               new text_field(wl,wh+th*6,DEV_AREA_VIEW_YOFF_SPEED, symbol_str("a_view_yspd"),"******",current_area->view_yoff_speed,
  1615.                          NULL)))))))));
  1616.     } else if (find)
  1617.     {
  1618.       current_area=find;
  1619.       current_area->active=1;
  1620.       if (find_top)
  1621.       state=DEV_DRAG_AREA_TOP;
  1622.       else state=DEV_DRAG_AREA_BOTTOM;
  1623.       the_game->need_refresh();
  1624.     } else if (current_area)
  1625.     {
  1626.       current_area->active=0;
  1627.       current_area=NULL;
  1628.       the_game->need_refresh();
  1629.     }
  1630.   }
  1631. }
  1632.  
  1633. void dev_controll::close_oedit_window()
  1634. {
  1635.   if (oedit)
  1636.   {
  1637.     prop->setd("oedit x",oedit->x);
  1638.     prop->setd("oedit y",oedit->y);
  1639.     eh->close_window(oedit);
  1640.     oedit=NULL;         
  1641.     edit_object=NULL;
  1642.   }
  1643. }
  1644.  
  1645. int screen_shot_on=1;
  1646. int sshot_fcount=-1;
  1647.  
  1648. void dev_controll::handle_event(event &ev)
  1649. {
  1650.   long x,y;
  1651.   if (link_object && (dlastx!=last_link_x || dlasty!=last_link_y))
  1652.   {
  1653.     last_link_x=dlastx;
  1654.     last_link_y=dlasty;
  1655.     the_game->need_refresh();
  1656.   }
  1657.  
  1658.   if (dev_menu && dev_menu->handle_event(ev,screen,eh)) return ;
  1659.  
  1660.   if (!current_level) return ;
  1661.  
  1662.   for (x=0;x<total_pals;x++)
  1663.     pal_wins[x]->handle_event(ev);
  1664.   if (ev.type==EV_MOUSE_MOVE)
  1665.   {
  1666.     dlastx=last_demo_mx;
  1667.     dlasty=last_demo_my;    
  1668.   }
  1669.   if (dev_console && dev_console->handle_event(ev,eh))
  1670.     return;
  1671.  
  1672.   if (ev.type==EV_KEY && ev.key==JK_F2)
  1673.     write_PCX(screen,pal,"scrnshot.pcx");
  1674.   else if (ev.type==EV_KEY && ev.key==JK_F3)
  1675.   {
  1676.     char name[100];
  1677.     sprintf(name,"shot%04d.pcx",screen_shot_on++);
  1678.     write_PCX(screen,pal,name);
  1679.   } else if (ev.type==EV_KEY && ev.key==JK_F5)
  1680.   {
  1681.     if (sshot_fcount!=-1)
  1682.     {
  1683.       sshot_fcount=-1;
  1684.       the_game->show_help(symbol_str("seqs_off"));
  1685.     }
  1686.     else
  1687.     {
  1688.       sshot_fcount=0;
  1689.       the_game->show_help(symbol_str("seqs_on"));
  1690.     }    
  1691.   }
  1692.  
  1693.   switch (state)
  1694.   {
  1695.     case DEV_MOUSE_RELEASE :
  1696.     {
  1697.       if (!ev.mouse_button)
  1698.         state=DEV_SELECT;    
  1699.     } break;
  1700.  
  1701.     case DEV_CREATE_OBJECT :
  1702.     {
  1703.       if (!ev.mouse_button)    
  1704.         state=DEV_MOVE_OBJECT;
  1705.     } break;
  1706.  
  1707.  
  1708.     case DEV_MOVE_OBJECT :
  1709.     {
  1710.       if (!edit_object)
  1711.       { state=DEV_SELECT; }
  1712.       else
  1713.       {
  1714.     if (ev.type==EV_MOUSE_MOVE)
  1715.     {
  1716.       the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_object->x,edit_object->y);      
  1717.       edit_object->x=snap_x(edit_object->x);
  1718.       edit_object->y=snap_y(edit_object->y);
  1719.       the_game->need_refresh();
  1720.     }
  1721.     else if (ev.mouse_button==1 && ev.window==NULL)
  1722.     {
  1723.       state=DEV_MOUSE_RELEASE;
  1724.       selected_object=edit_object=NULL;    
  1725.     }
  1726.     if (ev.window==NULL && ev.type==EV_KEY && ev.key=='d')
  1727.     {
  1728.       long xv=0,yv=100;
  1729.       edit_object->try_move(edit_object->x,edit_object->y,xv,yv,1);
  1730.       edit_object->y+=yv;
  1731.       state=DEV_SELECT;
  1732.       selected_object=edit_object=NULL;    
  1733.     }
  1734.       }
  1735.     } break;
  1736.     
  1737.  
  1738.     case DEV_MOVE_LIGHT :    
  1739.     {
  1740.       if (edit_light)
  1741.       {
  1742.     if (ev.type==EV_MOUSE_MOVE)
  1743.     {
  1744.       the_game->mouse_to_game(last_demo_mx,last_demo_my,edit_light->x,edit_light->y);
  1745.       edit_light->x=snap_x(edit_light->x);
  1746.       edit_light->y=snap_y(edit_light->y);
  1747.  
  1748.       edit_light->calc_range();
  1749.       the_game->need_refresh();
  1750.     } else if (ev.type==EV_KEY)
  1751.     {
  1752.       int rd=0;
  1753.       switch (ev.key)
  1754.       {
  1755.         case '+' :
  1756.         { 
  1757.           if (edit_light->type==9)
  1758.           {
  1759.         if (edit_light->inner_radius<64)
  1760.         { edit_light->inner_radius++; rd=1; }
  1761.           } else { edit_light->outer_radius++; rd=1; }
  1762.         } break;
  1763.         case '-' :
  1764.         {
  1765.           if (edit_light->type==9)
  1766.           {
  1767.         if (edit_light->inner_radius>0)
  1768.         { edit_light->inner_radius--; rd=1; }
  1769.           } else if (edit_light->outer_radius>edit_light->inner_radius+1)
  1770.           { edit_light->outer_radius--; rd=1; }
  1771.         } break;
  1772.         case JK_RIGHT :
  1773.         {
  1774.           if (edit_light->type==9)
  1775.           { edit_light->xshift++; rd=1; }
  1776.           else if (edit_light->xshift>0) 
  1777.           { edit_light->xshift--; rd=1; }
  1778.         } break;
  1779.         case JK_LEFT :
  1780.         {
  1781.           if (edit_light->type==9)
  1782.           {
  1783.         if (edit_light->xshift>1)
  1784.         { edit_light->xshift--; rd=1; }
  1785.           }
  1786.           else
  1787.           { edit_light->xshift++; rd=1; }
  1788.         } break;
  1789.         case JK_UP :
  1790.         {
  1791.           if (edit_light->type==9)
  1792.           { edit_light->yshift++; rd=1; }
  1793.           else if (edit_light->yshift>0) 
  1794.           { edit_light->yshift--; rd=1; }
  1795.         } break;
  1796.         case JK_DOWN :
  1797.         {
  1798.           if (edit_light->type==9)
  1799.           {
  1800.         if (edit_light->yshift>1)
  1801.         { edit_light->yshift--; rd=1; }
  1802.           }
  1803.           else
  1804.           { edit_light->yshift++; rd=1; }
  1805.         } break;
  1806.         
  1807.       }      
  1808.       if (rd)
  1809.       {
  1810.         edit_light->calc_range();
  1811.         the_game->need_refresh();
  1812.       }
  1813.  
  1814.     }
  1815.       }
  1816.  
  1817.       if ((ev.mouse_button==1 && ev.window==NULL) || !edit_light)
  1818.         state=DEV_MOUSE_RELEASE;
  1819.     } break;
  1820.  
  1821.  
  1822.     case DEV_DRAG_AREA_BOTTOM :
  1823.     {
  1824.       if (current_area)
  1825.       {
  1826.     long gx,gy;
  1827.     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
  1828.     if (gx>current_area->x && gy>current_area->y)
  1829.     {       
  1830.       if (gx-current_area->x!=current_area->w || gy-current_area->y!=current_area->h)
  1831.       {
  1832.         the_game->need_refresh();
  1833.         current_area->w=gx-current_area->x;
  1834.         current_area->h=gy-current_area->y;      
  1835.       }
  1836.     }
  1837.     if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
  1838.     {
  1839.       current_area->active=0;
  1840.       state=DEV_SELECT;
  1841.     }
  1842.       }
  1843.     } break;
  1844.  
  1845.     case DEV_DRAG_AREA_TOP :
  1846.     {
  1847.       if (current_area)
  1848.       {
  1849.     long gx,gy;
  1850.     the_game->mouse_to_game(last_demo_mx,last_demo_my,gx,gy);
  1851.     if (gx<current_area->x+current_area->w && gy<current_area->y+current_area->h)
  1852.     {       
  1853.       if (gx!=current_area->x || gy!=current_area->y)
  1854.       {
  1855.         the_game->need_refresh();
  1856.         current_area->x=gx;
  1857.         current_area->y=gy;
  1858.       }
  1859.     }
  1860.     if (ev.type==EV_MOUSE_BUTTON && !ev.mouse_button)
  1861.     {
  1862.       current_area->active=0;
  1863.       state=DEV_SELECT;
  1864.     }
  1865.       }
  1866.     } break;
  1867.  
  1868.     case DEV_SELECT :
  1869.     {
  1870.       if (dev&EDIT_MODE)
  1871.       {
  1872.     game_object *old=selected_object;      
  1873.     selected_object=NULL;
  1874.     if (ev.window==NULL)
  1875.     {    
  1876.       long rx,ry;
  1877.       the_game->mouse_to_game(last_demo_mx,last_demo_my,rx,ry);
  1878.  
  1879.       if (!(dev & MAP_MODE))
  1880.       {
  1881.         if (dev&DRAW_PEOPLE_LAYER)
  1882.               selected_object=current_level->find_object(rx,ry);
  1883.         light_source *old_light=selected_light;
  1884.         if (selected_object)
  1885.           selected_light=NULL;
  1886.         else
  1887.           selected_light=find_light(rx,ry);
  1888.         if (selected_light!=old_light)
  1889.           the_game->need_refresh();            
  1890.       } else { selected_light=NULL; }
  1891.  
  1892.       if (edit_mode==ID_DMODE_DRAW)
  1893.       {
  1894.         if (ev.mouse_button==1 && !selected_object && !selected_light)
  1895.         {
  1896.           long xs,ys;
  1897.           the_game->ftile_on(last_demo_mx,last_demo_my,xs,ys);
  1898.           if (xs>=0 && ys>=0 && xs<current_level->foreground_width() && 
  1899.           ys<current_level->foreground_height())          
  1900.           current_level->put_fg(xs,ys,raise_all ? make_above_tile(cur_fg) : cur_fg);
  1901.           the_game->need_refresh();
  1902.         } else if (ev.mouse_button==1 && !selected_object && !selected_light)
  1903.         {
  1904.           long xs,ys;
  1905.           the_game->btile_on(last_demo_mx,last_demo_my,xs,ys);
  1906.           if (xs>=0 && ys>=0 && xs<current_level->background_width() && 
  1907.           ys<current_level->background_height())
  1908.           current_level->put_bg(xs,ys,cur_fg);
  1909.           the_game->need_refresh();
  1910.         }
  1911.       } else if (edit_mode==ID_DMODE_AREA)
  1912.         area_handle_input(ev);
  1913.       else if (edit_mode==ID_DMODE_PICK)
  1914.         pick_handle_input(ev);                   
  1915.     }
  1916.     
  1917.     if (old!=selected_object)
  1918.         the_game->need_refresh();            
  1919.  
  1920.  
  1921.     if (ev.mouse_button)
  1922.     {
  1923.       if (selected_object)
  1924.       {
  1925.         if (edit_object && edit_object!=selected_object)      
  1926.              edit_object->add_object(selected_object);
  1927.  
  1928.         if (oedit)
  1929.           close_oedit_window();
  1930.          
  1931.         int bw=20+6,bh=16+6,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,th=eh->font()->height()+4;
  1932.  
  1933.         oedit=eh->new_window(prop->getd("oedit x",0),
  1934.                  prop->getd("oedit y",0),
  1935.                  -1,-1,new button_box(wl,wh,ID_NULL,1,
  1936.         new button(wl+bw*0,wh,DEV_OEDIT_OK,cash.img(dev_ok),
  1937.         new button(wl+bw*1,wh,DEV_OEDIT_MOVE,cash.img(dev_move),
  1938.         new button(wl+bw*2,wh,DEV_OEDIT_FRONT,cash.img(dev_front),
  1939.             new button(wl+bw*3,wh,DEV_OEDIT_BACK,cash.img(dev_back),
  1940.             new button(wl+bw*4,wh,DEV_OEDIT_COPY,cash.img(dev_copy),
  1941.         new button(wl+bw*0,wh+bh*1,DEV_OEDIT_DELETE,cash.img(dev_del),
  1942.                NULL)))))),
  1943.            new button(wl+bw*5,wh+bh*0,DEV_OEDIT_AI,cash.img(dev_ai),
  1944.  
  1945.            new button_box(wl+bw*1,wh+bh*1,DEV_OEDIT_CHAR_BOX,0,
  1946.            new button(wl+bw*1,wh+bh*1,DEV_OEDIT_LEFT,cash.img(dev_char_left),
  1947.            new button(wl+bw*2,wh+bh*1,DEV_OEDIT_RIGHT,cash.img(dev_char_right),NULL)),
  1948.  
  1949.            new button(wl+bw*3,wh+bh*1,DEV_OBJECTS_DELETE,cash.img(dev_objects),
  1950.            new button(wl+bw*4,wh+bh*1,DEV_LIGHTS_DELETE,cash.img(dev_lights),NULL))))),
  1951.                  symbol_str("l_EDIT"));
  1952.  
  1953.         
  1954.         edit_object=selected_object;    
  1955.       } else if (selected_light)
  1956.       {
  1957.         if (ledit)
  1958.         {
  1959.           prop->setd("ledit x",ledit->x);
  1960.           prop->setd("ledit x",ledit->y);
  1961.           eh->close_window(ledit);
  1962.         }
  1963.         int bw=20+6,bh=16+6,wl=WINDOW_FRAME_LEFT,wh=WINDOW_FRAME_TOP,th=eh->font()->height()+4;
  1964.         edit_light=selected_light;
  1965.         if (edit_object)
  1966.         {
  1967.           edit_object->add_light(edit_light);
  1968.           edit_light->known=1;
  1969.         }
  1970.         ledit=eh->new_window(prop->getd("ledit x",0),
  1971.                  prop->getd("ledit y",0),
  1972.                  -1,-1,
  1973.               new button_box(wl,wh,ID_NULL,1,
  1974.                    new button(wl+bw*0,wh,DEV_LEDIT_OK,cash.img(dev_ok),
  1975.                new button(wl+bw*1,wh,DEV_LEDIT_MOVE,cash.img(dev_move),
  1976.                   new button(wl+bw*2,wh,DEV_LEDIT_COPY,cash.img(dev_copy),
  1977.             new button(wl+bw*3,wh,DEV_LEDIT_DEL,cash.img(dev_del),NULL)))),
  1978.             new text_field(wl,wh+bh,DEV_LEDIT_W,      "W ","******",edit_light->xshift,
  1979.             new text_field(wl,wh+bh+th*1,DEV_LEDIT_H, "H ","******",edit_light->yshift,
  1980.           new text_field(wl,wh+bh+th*2,DEV_LEDIT_R1,"R1","******",(int)(edit_light->inner_radius),
  1981.          new text_field(wl,wh+bh+th*3,DEV_LEDIT_R2,"R2","******",(int)(edit_light->outer_radius),
  1982.                    NULL))))));
  1983.       }
  1984.       else if (ev.window==NULL)
  1985.       {
  1986.         if (dlastx>=0 && dlasty>=0 && edit_mode==ID_DMODE_DRAW)
  1987.         {
  1988.           if ((dev & DRAW_FG_LAYER) && ev.mouse_button==1)
  1989.           {    
  1990.         the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
  1991.         if (x>=0 && y>=0 && x<current_level->foreground_width() &&
  1992.             y<current_level->foreground_height())
  1993.         the_game->put_fg(x,y,raise_all ? make_above_tile(cur_fg) : cur_fg);
  1994.           }       
  1995.           if ((dev & DRAW_BG_LAYER) && ev.mouse_button==2)
  1996.           {      
  1997.         the_game->btile_on(last_demo_mx,last_demo_my,x,y);
  1998.         if (x>=0 && y>=0 && x<current_level->background_width() &&
  1999.             y<current_level->background_height())
  2000.         the_game->put_bg(x,y,cur_bg);
  2001.           }    
  2002.         } 
  2003.       }
  2004.     }
  2005.       }
  2006.     }
  2007.   }
  2008.  
  2009.   switch (ev.type)
  2010.   {
  2011.     case EV_MESSAGE :
  2012.     {
  2013.       switch (ev.message.id)
  2014.       { 
  2015.     case ID_DMODE_DRAW :
  2016.     case ID_DMODE_PICK :
  2017.     case ID_DMODE_FILL :
  2018.     case ID_DMODE_LINE : 
  2019.     case ID_DMODE_RECT :
  2020.     case ID_DMODE_BAR  : 
  2021.     case ID_DMODE_AREA :
  2022.     {
  2023.       edit_mode=ev.message.id;
  2024.     } break;
  2025. /*    case ID_ENLARGE_RENDER :
  2026.     {
  2027.       if (!small_render)
  2028.         double_render();
  2029.       else       
  2030.         single_render();
  2031.       
  2032.       view_shift_disabled=!view_shift_disabled;
  2033.     } break; */
  2034.  
  2035.     case ID_SEARCH :
  2036.     {
  2037.       toggle_search_window();
  2038.     } break;
  2039.     case ID_SEARCH_FOREWARD :
  2040.     { search_forward();
  2041.     } break;
  2042.     case ID_SEARCH_BACKWARD :
  2043.     { search_forward();
  2044.     } break;
  2045.     case ID_CANCEL :
  2046.     {
  2047.       if (mess_win)
  2048.       {
  2049.         eh->close_window(mess_win);
  2050.         mess_win=NULL;
  2051.       } break;
  2052.     } break;
  2053.     case ID_LEVEL_LOAD :
  2054.     {     
  2055.       if (!mess_win)
  2056.       {
  2057.         mess_win=file_dialog(eh,symbol_str("level_name"),current_level ? current_level->name() : "",
  2058.                  ID_LEVEL_LOAD_OK,symbol_str("ok_button"),ID_CANCEL,symbol_str("cancel_button"),
  2059.                  symbol_str("FILENAME"),ID_MESS_STR1);
  2060.         eh->grab_focus(mess_win);
  2061.       }
  2062.     } break;
  2063.     case ID_LEVEL_LOAD_OK :
  2064.     {
  2065.       char cmd[100];
  2066.       sprintf(cmd,"load %s",mess_win->read(ID_MESS_STR1));
  2067.       dev_cont->do_command(cmd,ev);
  2068.       eh->push_event(new event(ID_CANCEL,NULL));        // close window
  2069.     } break;    
  2070.     case ID_GAME_SAVE :
  2071.     {
  2072.       current_level->save("savegame.spe",1);
  2073.       the_game->show_help(symbol_str("saved_game"));
  2074.       the_game->need_refresh();      
  2075.     } break;
  2076.     case ID_LEVEL_SAVE :
  2077.     { if (current_level)
  2078.       {
  2079.         if (current_level->save(current_level->name(),0))
  2080.         {
  2081.           char msg[100];
  2082.           sprintf(msg,symbol_str("saved_level"),current_level->name());
  2083.           the_game->show_help(msg);
  2084.           the_game->need_refresh();
  2085.         }
  2086.       }
  2087.       else the_game->show_help("no current level, cannot save");
  2088.     } break;
  2089.     case ID_LEVEL_SAVEAS :
  2090.     {
  2091.       if (!mess_win)
  2092.       {
  2093.         mess_win=file_dialog(eh,symbol_str("saveas_name"),current_level ? current_level->name() : "untitled.spe",
  2094.                    ID_LEVEL_SAVEAS_OK,symbol_str("ok_button"),
  2095.                  ID_CANCEL,symbol_str("cancel_button"),
  2096.                  symbol_str("FILENAME"),ID_MESS_STR1);
  2097.         eh->grab_focus(mess_win);
  2098.       }
  2099.     } break;
  2100.     case ID_LEVEL_SAVEAS_OK :
  2101.     {
  2102.       if (current_level)
  2103.       {
  2104.         current_level->set_name(mess_win->read(ID_MESS_STR1));
  2105.         eh->push_event(new event(ID_CANCEL,NULL));        // close window after save
  2106.         eh->push_event(new event(ID_LEVEL_SAVE,NULL));        
  2107.       }
  2108.     } break;
  2109.     case ID_EDIT_SAVE :
  2110.     {
  2111.       do_command("esave",ev);
  2112.       the_game->show_help(symbol_str("edit_saved"));
  2113.     } break;
  2114.     case ID_CACHE_PROFILE :
  2115.     {
  2116.       if (current_level && !cash.prof_is_on())
  2117.       {
  2118.         cash.prof_init();
  2119.         the_game->show_help("Cache profiling is now on.");
  2120.       }
  2121.       else the_game->show_help("Cache profiling is already on!");
  2122.     } break;
  2123.  
  2124.     case ID_CACHE_PROFILE_END :  // ask the user for a file name to save as
  2125.     {
  2126.       if (cash.prof_is_on())
  2127.       {
  2128.         cash.prof_uninit();
  2129.         the_game->show_help(symbol_str("prof_off"));
  2130.       } else the_game->show_help(symbol_str("prof"));
  2131.     } break;
  2132.  
  2133.     case ID_LEVEL_NEW :
  2134.     {
  2135.       if (!mess_win)
  2136.       {
  2137.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2138.                new button(WINDOW_FRAME_LEFT+10,WINDOW_FRAME_TOP+20,ID_LEVEL_NEW_OK,symbol_str("YES"),
  2139.                         new button(WINDOW_FRAME_LEFT+40,WINDOW_FRAME_TOP+20,ID_CANCEL,symbol_str("NO"),
  2140.           new info_field(WINDOW_FRAME_LEFT,WINDOW_FRAME_TOP,ID_NULL,symbol_str("sure?"),NULL))),symbol_str("New?"));
  2141.         eh->grab_focus(mess_win);
  2142.       }
  2143.     } break;
  2144.     case ID_LEVEL_NEW_OK :
  2145.     {
  2146.       eh->push_event(new event(ID_CANCEL,NULL));  // close_window
  2147.       if (current_level)      
  2148.         delete current_level;     
  2149.       current_level=new level(100,100,"untitled.spe");
  2150.     } break;
  2151.     case ID_LEVEL_RESIZE :
  2152.     {
  2153.       if (!mess_win)
  2154.       {
  2155.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2156.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2157.             new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("width_"),"****",
  2158.                    current_level ? current_level->foreground_width() : 100,
  2159.             new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("height_"),"****",
  2160.                    current_level ? current_level->foreground_height() : 100,
  2161.                    new button(wl+10,wt+h*4,ID_LEVEL_RESIZE_OK,symbol_str("ok_button"),
  2162.                    new button(wt+40,wt+h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))),symbol_str("_scroll"));
  2163.       } 
  2164.     } break;
  2165.     case ID_LEVEL_RESIZE_OK :
  2166.     {
  2167.       if (current_level)
  2168.       {
  2169.         current_level->set_size(atoi(mess_win->read(ID_MESS_STR1)),
  2170.                     atoi(mess_win->read(ID_MESS_STR2)));
  2171.       } else the_game->show_help("Create a level first!");
  2172.       eh->push_event(new event(ID_CANCEL,NULL));  // close_window
  2173.     } break;
  2174.  
  2175.     case ID_SUSPEND :
  2176.     {
  2177.       dev^=SUSPEND_MODE;
  2178.       if (dev&SUSPEND_MODE)
  2179.         the_game->show_help(symbol_str("suspend_on"));
  2180.       else
  2181.          the_game->show_help(symbol_str("suspend_off"));
  2182.     } break;
  2183.     case ID_PLAY_MODE :
  2184.     {
  2185.       dev^=EDIT_MODE;
  2186.     } break;
  2187.     case ID_QUIT :
  2188.     {
  2189.       if (confirm_quit())
  2190.         do_command("quit",ev);
  2191.     } ;
  2192.     case ID_TOGGLE_MAP :
  2193.     {
  2194.       if (dev&MAP_MODE) dev-=MAP_MODE;
  2195.       else dev|=MAP_MODE;
  2196.       the_game->need_refresh();     
  2197.     } break;
  2198.     case ID_TOGGLE_LIGHT :
  2199.     {
  2200.       dev^=DRAW_LIGHTS;
  2201.       the_game->need_refresh();
  2202.     } break;
  2203.     case ID_RECORD_DEMO :
  2204.     {
  2205.       if (!mess_win)
  2206.       {
  2207.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2208.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2209.             new text_field(wl,wt+h*0,ID_RECORD_DEMO_FILENAME,
  2210.                    "demo filename","*******************",
  2211.                    "demo.dat",
  2212.                    new button(wl+10,wt+h*2,ID_RECORD_DEMO_OK,symbol_str("ok_button"),
  2213.                    new button(wt+40,wt+h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
  2214.       }
  2215.     } break;
  2216.  
  2217.         case ID_RECORD_DEMO_OK :
  2218.     {
  2219.       demo_man.set_state(demo_manager::RECORDING,mess_win->read(ID_RECORD_DEMO_FILENAME));
  2220.       eh->push_event(new event(ID_CANCEL,NULL));        // close window      
  2221.     } break;
  2222.  
  2223.     case ID_PLAY_DEMO :
  2224.     {
  2225.       if (!mess_win)
  2226.       {
  2227.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2228.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2229.             new text_field(wl,wt+h*0,ID_PLAY_DEMO_FILENAME,
  2230.                    "demo filename","*******************",
  2231.                    "demo.dat",
  2232.                    new button(wl+10,wt+h*2,ID_PLAY_DEMO_OK,symbol_str("ok_button"),
  2233.                    new button(wt+40,wt+h*2,ID_CANCEL,symbol_str("cancel_button"),NULL))));
  2234.       }
  2235.     } break;
  2236.  
  2237.         case ID_PLAY_DEMO_OK :
  2238.     {
  2239.       demo_man.set_state(demo_manager::PLAYING,mess_win->read(ID_PLAY_DEMO_FILENAME));
  2240.       eh->close_window(mess_win);
  2241.       mess_win=NULL;
  2242.     } break; 
  2243.  
  2244.     case ID_SET_SCROLL :
  2245.     {
  2246.       if (!mess_win)
  2247.       {
  2248.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2249.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2250.             new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("x_mul"),"****",bg_xmul,
  2251.             new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("x_div"),"****",bg_xdiv,
  2252.             new text_field(wl,wt+h*2,ID_MESS_STR3,symbol_str("y_mul"),"****",bg_ymul,
  2253.             new text_field(wl,wt+h*3,ID_MESS_STR4,symbol_str("y_div"),"****",bg_ydiv,
  2254.                    new button(wl+10,wt+h*4,ID_SET_SCROLL_CHECK,symbol_str("ok_button"),
  2255.                    new button(wt+40,wt+h*4,ID_CANCEL,symbol_str("cancel_button"),NULL)))))),symbol_str("_scroll"));
  2256.       } 
  2257.     } break;
  2258.     case ID_SET_SCROLL_CHECK :
  2259.     {
  2260.       int tbg_xmul=atoi(mess_win->read(ID_MESS_STR1));
  2261.       int tbg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
  2262.       int tbg_ymul=atoi(mess_win->read(ID_MESS_STR3));
  2263.       int tbg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
  2264.  
  2265.       if ( (((float)tbg_xmul/(float)tbg_xdiv) < ((float)bg_xmul/(float)bg_xdiv)) ||
  2266.           (((float)tbg_ymul/(float)tbg_ydiv) < ((float)bg_ymul/(float)bg_ydiv)))
  2267.       {
  2268.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2269.  
  2270.         warn_win=eh->new_window(xres/2-40,yres/2-40,-1,-1,
  2271.                   new info_field(wl,wt,ID_NULL,
  2272.                       symbol_str("back_loss"),
  2273.                       new button(wl+10,wt+h*4,ID_SET_SCROLL_OK,symbol_str("ok_button"),
  2274.                       new button(wt+40,wt+h*4,ID_WARN_CANCEL,symbol_str("cancel_button"),NULL))),
  2275.                     symbol_str("WARNING"));
  2276.         eh->grab_focus(warn_win);
  2277.       } else eh->push_event(new event(ID_SET_SCROLL_OK,NULL));
  2278.     } break;
  2279.     case ID_WARN_CANCEL :
  2280.     {
  2281.       eh->close_window(warn_win); warn_win=NULL;
  2282.       eh->push_event(new event(ID_CANCEL,NULL));
  2283.     } break;
  2284.     case ID_SET_SCROLL_OK :
  2285.     {
  2286.       if (warn_win) { eh->close_window(warn_win); warn_win=NULL; }
  2287.       bg_xmul=atoi(mess_win->read(ID_MESS_STR1));
  2288.       bg_xdiv=atoi(mess_win->read(ID_MESS_STR2));
  2289.       bg_ymul=atoi(mess_win->read(ID_MESS_STR3));
  2290.       bg_ydiv=atoi(mess_win->read(ID_MESS_STR4));
  2291.       eh->push_event(new event(ID_CANCEL,NULL));        // close window
  2292.     } break;
  2293.  
  2294.     case ID_CENTER_PLAYER :
  2295.     {
  2296.        do_command("center",ev); break;
  2297.     } break;
  2298.  
  2299.     case ID_INTERPOLATE_DRAW :  
  2300.     {
  2301.       interpolate_draw=!interpolate_draw;
  2302.     } break;
  2303.  
  2304.     case ID_DISABLE_AUTOLIGHT : 
  2305.     {
  2306.       disable_autolight=!disable_autolight;
  2307.     } break;
  2308.  
  2309.     case ID_ADD_PALETTE :
  2310.     {
  2311.       if (!mess_win)
  2312.       {
  2313.         int wl=WINDOW_FRAME_LEFT,wt=WINDOW_FRAME_TOP,h=eh->font()->height()+8;
  2314.         mess_win=eh->new_window(xres/2,yres/2,-1,-1,
  2315.             new text_field(wl,wt+h*0,ID_MESS_STR1,symbol_str("ap_width"),"****",2,
  2316.             new text_field(wl,wt+h*1,ID_MESS_STR2,symbol_str("ap_height"),"****",2,
  2317.             new text_field(wl,wt+h*2,ID_MESS_STR3,symbol_str("ap_name"),"***********","pal",
  2318.                    new button(wl+10,wt+h*3,ID_ADD_PALETTE_OK,symbol_str("ok_button"),
  2319.                    new button(wt+40,wt+h*3,ID_CANCEL,symbol_str("cancel_button"),NULL))))),symbol_str("ap_pal"));
  2320.       } 
  2321.     } break;
  2322.     case ID_ADD_PALETTE_OK :
  2323.     {
  2324.       char name[70];
  2325.       sprintf(name,"(add_palette \"%s\" %d %d)",mess_win->read(ID_MESS_STR3),
  2326.           atoi(mess_win->read(ID_MESS_STR1)),
  2327.           atoi(mess_win->read(ID_MESS_STR2)));
  2328.       char *s=name;
  2329.       eval(compile(s));
  2330.       eh->push_event(new event(ID_CANCEL,NULL));        // close window
  2331.     } break;
  2332.     case ID_TOGGLE_DELAY :
  2333.     {
  2334.       the_game->toggle_delay(); break;
  2335.     } break;
  2336.  
  2337.     case ID_SMALL_MODE :
  2338.     {
  2339.       make_screen_size(311,160); break;
  2340.     } break;
  2341.     case ID_CLEAR_WEAPONS :
  2342.     {
  2343.       event ev;
  2344.       do_command("clear_weapons",ev); 
  2345.     } break;
  2346.     case ID_GOD_MODE :
  2347.     {
  2348.       for (view *v=player_list;v;v=v->next)
  2349.         v->god=!v->god;
  2350.     } break;
  2351.     case ID_MOUSE_SCROLL :
  2352.     {
  2353.       mouse_scrolling=!mouse_scrolling;
  2354.       prop->setd("mouse_scrolling",mouse_scrolling);
  2355.       if (mouse_scrolling)
  2356.         the_game->show_help(symbol_str("ms_on"));
  2357.       else
  2358.         the_game->show_help(symbol_str("ms_off"));
  2359.     } break;
  2360.  
  2361.     case ID_LOCK_PALETTES :
  2362.     {
  2363.       palettes_locked=!palettes_locked;
  2364.       prop->setd("palettes_locked",palettes_locked);
  2365.       if (palettes_locked)
  2366.         the_game->show_help(symbol_str("pal_lock"));
  2367.       else the_game->show_help(symbol_str("pal_unlock"));      
  2368.     } break;
  2369.  
  2370.     case ID_DISABLE_VIEW_SHIFT :
  2371.     {
  2372.       view_shift_disabled=!view_shift_disabled;
  2373.       prop->setd("view_shift_disabled",view_shift_disabled);
  2374.       if (view_shift_disabled)
  2375.         the_game->show_help(symbol_str("vs_dis"));
  2376.       else the_game->show_help(symbol_str("vs_en"));      
  2377.     } break; 
  2378.  
  2379.     case ID_WIN_FORE :
  2380.     { 
  2381.       toggle_fgw();
  2382.     } break;
  2383.     case ID_WIN_BACK :
  2384.     { 
  2385.       toggle_bgw();
  2386.     } break;
  2387.     case ID_WIN_OBJECTS :
  2388.     { 
  2389.       toggle_omenu();
  2390.     } break;
  2391.     case ID_WIN_PALETTES :
  2392.     { 
  2393.       toggle_pmenu();
  2394.     } break;
  2395.     case ID_WIN_LIGHTING :
  2396.     { 
  2397.       toggle_light_window();
  2398.     } break;
  2399.     case ID_WIN_LAYERS :
  2400.     {
  2401.       toggle_show_menu(); 
  2402.     } break;
  2403.     case ID_WIN_CONSOLE :
  2404.     {
  2405.       if (dev_console) dev_console->toggle();
  2406.     } break;
  2407.     case ID_WIN_TOOLBAR :
  2408.     {
  2409.       toggle_toolbar();
  2410.     } break;
  2411.  
  2412.     case DEV_AMBIENT :
  2413.     { if (!ambw) make_ambient(); } break;
  2414.     case DEV_AREA_OK :
  2415.     { close_area_win(1); } break;
  2416.     case DEV_AREA_DELETE :
  2417.     { close_area_win(0);
  2418.       if (current_area && current_level)
  2419.       {
  2420.         if (current_level->area_list==current_area)
  2421.           current_level->area_list=current_level->area_list->next;
  2422.         else
  2423.         {
  2424.           area_controller *a=current_level->area_list,*l=NULL;
  2425.           for (;a!=current_area && a;a=a->next) { l=a; }
  2426.           l->next=a->next;
  2427.           delete a;
  2428.         }
  2429.         current_area=NULL;
  2430.         the_game->need_refresh();
  2431.       }
  2432.     } break;
  2433.     case DEV_AI_OK :
  2434.       close_ai_window(); break;
  2435.     case DEV_OEDIT_AI :
  2436.       make_ai_window(edit_object); break;
  2437.     case DEV_OBJECTS_DELETE :
  2438.     {
  2439.       if (edit_object)
  2440.       {
  2441.         for (int i=0;i<edit_object->total_objects();i++)
  2442.           edit_object->remove_object(edit_object->get_object(0));
  2443.         the_game->need_refresh();        
  2444.       }
  2445.     } break;
  2446.  
  2447.     case DEV_LIGHTS_DELETE :
  2448.     {
  2449.       if (edit_object)
  2450.       {
  2451.         for (int i=0;i<edit_object->total_lights();i++)
  2452.           edit_object->remove_light(edit_object->get_light(0));
  2453.         the_game->need_refresh();        
  2454.       }
  2455.     } break;
  2456.  
  2457.     case DEV_LEDIT_DEL :
  2458.     {
  2459.       prop->setd("ledit x",ledit->x);
  2460.       prop->setd("ledit y",ledit->y);
  2461.       eh->close_window(ledit); ledit=NULL;
  2462.       if (current_level)
  2463.         current_level->remove_light(edit_light);
  2464.       else
  2465.         delete_light(edit_light);
  2466.       edit_light=NULL;
  2467.       the_game->need_refresh();
  2468.     } break;
  2469.     case DEV_LEDIT_OK :
  2470.     {
  2471.       edit_light->xshift=atoi(ledit->read(DEV_LEDIT_W));
  2472.       edit_light->yshift=atoi(ledit->read(DEV_LEDIT_H));
  2473.       edit_light->inner_radius=atoi(ledit->read(DEV_LEDIT_R1));
  2474.       edit_light->outer_radius=atoi(ledit->read(DEV_LEDIT_R2));
  2475.       if (edit_light->outer_radius<=edit_light->inner_radius)
  2476.       {
  2477.         edit_light->inner_radius=edit_light->outer_radius-1;
  2478.         if (edit_light->inner_radius<1)
  2479.         {
  2480.           edit_light->inner_radius=1;
  2481.           edit_light->outer_radius=2;
  2482.         }
  2483.       }
  2484.  
  2485.       edit_light->calc_range();
  2486.       edit_light=NULL;
  2487.       prop->setd("ledit x",ledit->x);
  2488.       prop->setd("ledit y",ledit->y);
  2489.       eh->close_window(ledit); ledit=NULL;
  2490.       the_game->need_refresh();      
  2491.     } break;
  2492.     case DEV_LEDIT_MOVE :
  2493.     {
  2494.       prop->setd("ledit x",ledit->x);
  2495.       prop->setd("ledit y",ledit->y);
  2496.       eh->close_window(ledit); ledit=NULL;
  2497.       state=DEV_MOVE_LIGHT;
  2498.     } break;
  2499.     case DEV_LEDIT_COPY :
  2500.     {
  2501.       edit_light=edit_light->copy();
  2502.       prop->setd("ledit x",ledit->x);
  2503.       prop->setd("ledit y",ledit->y);
  2504.       eh->close_window(ledit); ledit=NULL;      
  2505.       state=DEV_MOVE_LIGHT;
  2506.     } break;
  2507.  
  2508.  
  2509.     case DEV_LIGHT0 :
  2510.     case DEV_LIGHT1 :
  2511.     case DEV_LIGHT2 :
  2512.     case DEV_LIGHT3 :
  2513.     case DEV_LIGHT4 :
  2514.     case DEV_LIGHT5 :
  2515.     case DEV_LIGHT6 :
  2516.     case DEV_LIGHT7 :
  2517.     case DEV_LIGHT8 :
  2518.     case DEV_LIGHT9 :
  2519.     {
  2520.       long lx,ly;
  2521.       the_game->mouse_to_game(last_demo_mx,last_demo_my,lx,ly);
  2522.       lx=snap_x(lx);
  2523.       ly=snap_y(ly);
  2524.       edit_light=add_light_source(ev.message.id-DEV_LIGHT0,lx,ly,
  2525.                        atoi(lightw->read(DEV_LIGHTR1)),
  2526.                        atoi(lightw->read(DEV_LIGHTR2)),
  2527.                        atoi(lightw->read(DEV_LIGHTW)),
  2528.                        atoi(lightw->read(DEV_LIGHTH)));
  2529.       state=DEV_MOVE_LIGHT;                       
  2530.     } break;
  2531.     case ID_RAISE_ALL :
  2532.     {
  2533.       raise_all=!raise_all;
  2534.       prop->setd("raise_all",raise_all);
  2535.       if (raise_all)
  2536.         the_game->show_help(symbol_str("fg_r"));
  2537.       else
  2538.         the_game->show_help(symbol_str("fg_l"));
  2539.     } break;
  2540.     case DEV_OEDIT_COPY :
  2541.     {
  2542.       game_object *use=copy_object;
  2543.       if (!use) use=edit_object;
  2544.       if (use)
  2545.       {        
  2546.         game_object *old=use;
  2547.         close_oedit_window();
  2548.         if (use->controller())
  2549.           the_game->show_help(symbol_str("no_clone"));
  2550.         else
  2551.         {
  2552.           edit_object=old->copy();
  2553.  
  2554.           current_level->add_object(edit_object);
  2555.           the_game->need_refresh();
  2556.           state=DEV_MOVE_OBJECT; 
  2557.  
  2558.           close_oedit_window();
  2559.           copy_object=NULL;
  2560.         }
  2561.       }
  2562.     } break;
  2563.     case DEV_OEDIT_LEFT :
  2564.     {
  2565.       if (edit_object)
  2566.       {
  2567.         the_game->need_refresh();
  2568.         edit_object->direction=-1;
  2569.       }
  2570.     } break;
  2571.     case DEV_OEDIT_RIGHT :
  2572.     {
  2573.       if (edit_object)
  2574.       {
  2575.         the_game->need_refresh();
  2576.         edit_object->direction=1;
  2577.       }
  2578.     } break;
  2579.  
  2580.  
  2581.     case DEV_COMMAND_OK :
  2582.     {
  2583.       char cmd[100];
  2584.       strcpy(cmd,commandw->inm->get(DEV_COMMAND)->read());        
  2585.       prop->setd("commandw x",commandw->x);
  2586.       prop->setd("commandw y",commandw->y);
  2587.       eh->close_window(commandw); 
  2588.       commandw=NULL;
  2589.       do_command(cmd,ev);
  2590.     } break;
  2591.  
  2592.     case ID_SHOW_FPS :
  2593.     { fps_on=!fps_on; } break;
  2594.     case ID_PROFILE :
  2595.     { profile_toggle(); 
  2596.       profile_on=!profile_on; 
  2597.     } break;
  2598.       
  2599.     case ID_TOGGLE_NAMES : { show_names=!show_names; } break;
  2600.     case DEV_QUIT : the_game->end_session(); break;
  2601.     case DEV_EDIT_FG : dev=1; break; //the_game->draw(); break;
  2602.     case DEV_EDIT_BG : dev=2; break; //the_game->draw(); break;
  2603.     case DEV_EDIT_FGBG : dev=3; break; //the_game->draw(); break;
  2604.     case DEV_PLAY : dev=0; break; //the_game->draw(); break;
  2605.     case SHOW_FOREGROUND :
  2606.     { dev=dev^DRAW_FG_LAYER; the_game->need_refresh(); } break;
  2607.     case SHOW_FOREGROUND_BOUND :
  2608.     { dev=dev^DRAW_FG_BOUND_LAYER; the_game->need_refresh(); } break;
  2609.     case SHOW_BACKGROUND :
  2610.     { dev=dev^DRAW_BG_LAYER; the_game->need_refresh(); } break;
  2611.     case SHOW_CHARACTERS :
  2612.     { dev=dev^DRAW_PEOPLE_LAYER; the_game->need_refresh(); } break;
  2613.     case SHOW_LIGHT :
  2614.     { dev=dev^DRAW_LIGHTS; the_game->need_refresh(); } break;        
  2615.     case SHOW_LINKS :
  2616.     { dev=dev^DRAW_LINKS;  the_game->need_refresh(); } break;
  2617.       
  2618.  
  2619.     case DEV_CREATE : 
  2620.     {      
  2621.       int val=get_omenu_item(((pick_list *)ev.message.data)->get_selection());
  2622.       char cmd[100];
  2623.       sprintf(cmd,"create %s",object_names[val]);
  2624.       do_command(cmd,ev);
  2625.       state=DEV_CREATE_OBJECT;
  2626.       dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);        
  2627.     }             
  2628.     break;    
  2629.  
  2630.     case DEV_PALETTE :
  2631.     {
  2632.       int val=((pick_list *)ev.message.data)->get_selection();        
  2633.       pal_wins[val]->open_window();
  2634.     } break;
  2635.  
  2636.     case DEV_MUSIC_PICKLIST : 
  2637.     {      
  2638. /*        int *val=((int *)((pick_list *)ev.message.data)->read());
  2639.         if (current_song) delete current_song;
  2640.         current_song=new song(song_list[*val]);
  2641.         current_song->play();        */
  2642.     }             
  2643.     break;         
  2644.  
  2645.     case DEV_OEDIT_OK : 
  2646.     { close_oedit_window(); } break;
  2647.       
  2648.     case DEV_OEDIT_DELETE : 
  2649.     {
  2650.       selected_object=edit_object;
  2651.       do_command("delete",ev);
  2652.       close_oedit_window();
  2653.     }
  2654.     break;
  2655.       
  2656.     case DEV_OEDIT_FRONT : 
  2657.     {
  2658.       do_command("to_front",ev);
  2659.       close_oedit_window();                  
  2660.     }
  2661.     break;
  2662.  
  2663.     case DEV_OEDIT_BACK : 
  2664.     {
  2665.       do_command("to_back",ev);
  2666.       close_oedit_window();                  
  2667.     }
  2668.     break;
  2669.  
  2670.     case DEV_OEDIT_MOVE :        
  2671.     {
  2672.       game_object *o=edit_object;
  2673.       close_oedit_window();
  2674.       edit_object=o;
  2675.       do_command("move",ev);
  2676.     }
  2677.     break;     
  2678.       }
  2679.     } break;
  2680.  
  2681.  
  2682.     case EV_CLOSE_WINDOW :
  2683.     {
  2684.       if (ev.window)
  2685.       {      
  2686.     if (ev.window==commandw)
  2687.     {
  2688.       prop->setd("commandw x",commandw->x);
  2689.       prop->setd("commandw y",commandw->y);      
  2690.       eh->close_window(commandw); 
  2691.       commandw=NULL;    
  2692.     } else if (ev.window==oedit)
  2693.       close_oedit_window();
  2694.     else if (ev.window==ambw)
  2695.     { eh->close_window(ambw); ambw=NULL; }
  2696.     else if (ev.window==backw) toggle_bgw();
  2697.     else if (ev.window==forew) toggle_fgw();
  2698.     else if (ev.window==lightw) toggle_light_window();
  2699.     else if (ev.window==show_menu) toggle_show_menu();
  2700.     else if (ev.window==pmenu) toggle_pmenu();
  2701.     else if (ev.window==tbw) toggle_toolbar();
  2702.     else if (ev.window==omenu) toggle_omenu();
  2703.     else if (ev.window==memprof) toggle_memprof();
  2704.     else if (ev.window==search_window) toggle_search_window();
  2705.     else if (profile_handle_event(ev))  profile_on=!profile_on;
  2706.     else if (chat->chat_event(ev)) chat->toggle();
  2707.     
  2708.       }    
  2709.     }
  2710.     break;
  2711.     case EV_KEYRELEASE :
  2712.     {
  2713.       if (ev.key==JK_CTRL_L)
  2714.       {
  2715.         if (!edit_object && link_object && selected_object && link_object!=selected_object)
  2716.     {
  2717.       link_object->add_object(selected_object);
  2718.       if (S_LINK_SND>0) cash.sfx(S_LINK_SND)->play(sfx_volume/2);
  2719.       the_game->need_refresh();
  2720.     }
  2721.  
  2722.     link_object=NULL;
  2723.       }
  2724.     } break;
  2725.     case EV_KEY :
  2726.     {    
  2727.       if (backw && ev.window==backw)
  2728.       { if (ev.key=='-' && bg_scale<the_game->btile_height()/2)
  2729.     { toggle_bgw();
  2730.       bg_scale++;
  2731.       toggle_bgw();
  2732.     } else if (ev.key=='+' && bg_scale>1)
  2733.     { toggle_bgw();
  2734.       bg_scale--;
  2735.       toggle_bgw();
  2736.     } else if (ev.key=='b') toggle_bgw();
  2737.     else if (ev.key=='B') { toggle_bgw(); bg_w++; if (bg_w>6) bg_w=1; toggle_bgw(); }
  2738.       }
  2739.       if (forew && ev.window==forew)
  2740.       { if (ev.key=='-' && fg_scale<the_game->ftile_height()/2)
  2741.     { toggle_fgw();
  2742.       fg_scale++;
  2743.       toggle_fgw();
  2744.     } else if (ev.key=='+' && fg_scale>1)
  2745.     { toggle_fgw();
  2746.       fg_scale--;
  2747.       toggle_fgw();
  2748.     } else if (ev.key=='i')
  2749.     {
  2750.       toggle_fgw();
  2751.       fg_reversed=!fg_reversed;
  2752.       prop->setd("fg_reversed",fg_reversed);
  2753.       toggle_fgw();
  2754.     } else if (ev.key=='f') toggle_fgw();
  2755.  
  2756.     else if (ev.key=='F') { toggle_fgw(); fg_w++; if (fg_w>6) fg_w=1; toggle_fgw(); }
  2757.       }
  2758.       if (ev.window==NULL || ev.window==pmenu ||
  2759.       ev.window==forew || is_pal_win(ev.window))  // main window actions
  2760.       {          
  2761.     switch (ev.key)
  2762.     {
  2763.       case JK_CTRL_L : if (!edit_object && !link_object) { link_object=selected_object; }
  2764.       case 'n' : current_level->next_focus(); break;                       
  2765. //      case '/' : if (dev_console) dev_console->toggle(); break;      
  2766.       case 't' :
  2767.       {
  2768.         if (ev.window==NULL || ev.window==forew)
  2769.         {
  2770.           the_game->ftile_on(last_demo_mx,last_demo_my,x,y);
  2771.           fg_fill(cur_fg,x,y,NULL);
  2772.         }
  2773.       } break;
  2774.       case 'f' : toggle_fgw(); break;
  2775.       case 'M' : toggle_music_window(); break;                      
  2776.  
  2777.       case 'b' : toggle_bgw(); break;
  2778.       case 'a' : toggle_toolbar(); break;
  2779.       case 'A' : { if (selected_object)
  2780.                {
  2781.              if (oedit) eh->push_event(new event(DEV_OEDIT_OK,NULL));               
  2782.              make_ai_window(selected_object);
  2783.                }
  2784.              } break;
  2785.              
  2786.       case 'o' : toggle_omenu(); break;                
  2787.  
  2788.       case '<' : do_command("to_back",ev); break;
  2789.  
  2790.       case '>' : do_command("to_front",ev); break;
  2791.       case 'p' : toggle_pmenu(); break;                
  2792.       case 'P' : profile_toggle(); break;
  2793.       case '|' : toggle_memprof(); break;
  2794.       case '.' : 
  2795.       { 
  2796.         if (last_created_type>=0)
  2797.         {
  2798.           int val=last_created_type;
  2799.           char cmd[100];
  2800.           sprintf(cmd,"create %s",object_names[val]);
  2801.           do_command(cmd,ev);
  2802.           state=DEV_CREATE_OBJECT;
  2803.           dev|=(EDIT_MODE | DRAW_PEOPLE_LAYER);        
  2804.         }
  2805.       }             
  2806.       break;    
  2807.  
  2808.  
  2809.       case 'd' : { do_command("delete",ev);  the_game->need_refresh(); } break;
  2810.       case 'i' : 
  2811.       {       
  2812.         fg_reversed=!fg_reversed;
  2813.         prop->setd("fg_reversed",fg_reversed);
  2814.         if (forew)
  2815.         {
  2816.           toggle_fgw();
  2817.           toggle_fgw();
  2818.         }
  2819.       } break;
  2820.       case 'l' : toggle_light_window(); break;
  2821.       case '!' :
  2822.       case '@' :
  2823.       case '#' :
  2824.       case '$' :
  2825.       case '%' :
  2826.       case '^' :
  2827.       case '&' :
  2828.       case '*' :
  2829.       case '(' :
  2830.       case ')' :
  2831.  
  2832.       case '0' :
  2833.       case '1' :
  2834.       case '2' :
  2835.       case '3' :
  2836.       case '4' :
  2837.       case '5' :
  2838.       case '6' :
  2839.       case '7' :
  2840.       case '8' :
  2841.       case '9' : do_command("set_aitype",ev); break;
  2842.       case 'c' : do_command("center",ev); break;
  2843.       case 'C' :  
  2844.       if (selected_object && selected_object->controller()==NULL)
  2845.       { copy_object=selected_object;
  2846.             eh->push_event(new event(DEV_OEDIT_COPY,NULL)); } break;
  2847.       
  2848.       case 'D' : the_game->toggle_delay(); break;
  2849.       case 'L' : toggle_show_menu(); break;
  2850.       case '`' : do_command("fg_select",ev); break;
  2851.       case 'r' : { do_command("toggle_fg_raise",ev); the_game->need_refresh(); }  break;
  2852.       case '[' : do_command("fg_add -1",ev); break;
  2853.       case ']' : do_command("fg_add 1",ev); break;
  2854.       case 'R' : do_command("reload",ev); break;
  2855.       case 'w' : 
  2856.       {       
  2857.         long rx,ry;
  2858.         the_game->mouse_to_game(dlastx,dlasty,rx,ry);
  2859.         char msg[100]; sprintf(msg,symbol_str("mouse_at"),rx,ry);
  2860.         the_game->show_help(msg);
  2861.         the_game->need_refresh();
  2862.       } break;
  2863.       case 'k' :
  2864.       {
  2865.         if (selected_object && selected_object->total_objects()) 
  2866.           selected_object->remove_object(selected_object->get_object(0));
  2867.         the_game->need_refresh();
  2868.       } break;
  2869.       case 'K' :
  2870.       {
  2871.         if (selected_object && selected_object->total_objects()) 
  2872.           selected_object->remove_object(selected_object->get_object(selected_object->total_objects()-1));
  2873.         the_game->need_refresh();
  2874.       } break;
  2875.       case 'j' :
  2876.       {
  2877.         if (current_level && player_list && player_list->focus)
  2878.         {
  2879.           long rx,ry;
  2880.           the_game->mouse_to_game(dlastx,dlasty,rx,ry);
  2881.           player_list->focus->x=rx;
  2882.           player_list->focus->y=ry;
  2883.           do_command("center",ev);
  2884.           the_game->need_refresh();
  2885.         }
  2886.       } break;
  2887.       case 'z' : do_command("clear_weapons",ev); break;      
  2888.       case 'Z' : if (dev&EDIT_MODE)
  2889.       { view *v=the_game->view_in(last_demo_mx,last_demo_my);
  2890.         if (v)
  2891.         {
  2892.           v->god=!v->god;
  2893.           sbar.redraw(screen);
  2894.         }
  2895.       } break;
  2896.       case ' ' : 
  2897.       {
  2898.         if (dev & EDIT_MODE)
  2899.         {
  2900.           if (selected_object)
  2901.           {
  2902.         if (oedit)
  2903.           close_oedit_window();
  2904.         edit_object=selected_object;
  2905.         do_command("move",ev);
  2906.           } else if (selected_light)
  2907.           {
  2908.         if (ledit)
  2909.         {
  2910.           eh->close_window(ledit);
  2911.           ledit=NULL;
  2912.         }
  2913.         edit_light=selected_light;
  2914.         do_command("move_light",ev);
  2915.           }
  2916.           
  2917.         } break;        
  2918.       }      
  2919.       case 'x' : 
  2920.       {
  2921.         if (selected_object) 
  2922.         { if (selected_object->direction>0)
  2923.           selected_object->direction=-1;
  2924.         else selected_object->direction=1;
  2925.         }
  2926.       } break;
  2927.       
  2928.     }      
  2929.       }
  2930.     }
  2931.   }
  2932.   
  2933.  
  2934. }
  2935.  
  2936.  
  2937. void dev_controll::add_palette(void *args)
  2938. {
  2939.   total_pals++;
  2940.   pal_wins=(pal_win **)jrealloc(pal_wins,sizeof(pal_win *)*total_pals,"edit pal array");
  2941.   pal_wins[total_pals-1]=new pal_win(args);
  2942. }
  2943.  
  2944.  
  2945. pal_win::pal_win(void *args) 
  2946. {
  2947.   int i=0;
  2948.   Cell *ao=(Cell *)args;
  2949.  
  2950.   name=strcpy((char *)jmalloc(strlen(lstring_value(CAR(args)))+1,
  2951.                   "pal name"),lstring_value(CAR(args)));
  2952.   ao=CDR(ao);
  2953.   scale=w=h=1;
  2954.   x=y=0;
  2955.   
  2956.   if (!NILP(ao))
  2957.   {
  2958.     w=lnumber_value(CAR(ao)); ao=CDR(ao);
  2959.     if (!NILP(ao))
  2960.     {
  2961.       h=lnumber_value(CAR(ao)); ao=CDR(ao);
  2962.       if (!NILP(ao))
  2963.       {
  2964.     x=lnumber_value(CAR(ao)); ao=CDR(ao);
  2965.     if (!NILP(ao))
  2966.     {
  2967.       y=lnumber_value(CAR(ao)); ao=CDR(ao);
  2968.       if (!NILP(ao))
  2969.         scale=lnumber_value(CAR(ao)); ao=CDR(ao);
  2970.     }
  2971.       }
  2972.     }
  2973.   }
  2974.  
  2975.   if (w<=0) w=0;
  2976.   if (h<=0) h=0;
  2977.  
  2978.   pat=(unsigned short *)jmalloc(w*h*sizeof(unsigned short),"palwin::pat");
  2979.   memset(pat,0,sizeof(unsigned short)*w*h);   // set the palette to black if no parameters are given
  2980.   while (!NILP(ao))   // loop until we run out of parameters
  2981.   {
  2982.     if (i>w*h)
  2983.     { 
  2984.       lbreak("to many parameters to add_palette ");
  2985.       exit(0);
  2986.     }
  2987.     pat[i]=lnumber_value(CAR(ao));
  2988.     // make sure the tile that they suggested exists
  2989.     if (pat[i]<=0 || pat[i]>nforetiles || foretiles[pat[i]]<0)
  2990.       pat[i]=0;    
  2991.     ao=CDR(ao);
  2992.     i++;
  2993.   }
  2994.   last_selected=-1;
  2995.   me=NULL;
  2996.   open_window();
  2997. }
  2998.  
  2999. void pal_win::open_window()
  3000.   if (me) close_window();
  3001.   me=eh->new_window(x,y,w*f_wid/scale,h*f_hi/scale,NULL,name);
  3002.   draw();
  3003. }
  3004.  
  3005. void pal_win::close_window()
  3006. {
  3007.   if (me)       // dont' close the window if the window is already closed
  3008.   {
  3009.     x=me->x;    //  save the old poisition of the window so that when we  open it
  3010.                 //  it will be in the same spot
  3011.     y=me->y;
  3012.     eh->close_window(me);
  3013.     me=NULL;
  3014.     
  3015.   }
  3016. }
  3017.  
  3018. #ifdef __POWERPC__
  3019. #pragma global_optimizer on
  3020. #endif
  3021.  
  3022. void pal_win::draw()
  3023. {
  3024.   int i,find=-1,d=cur_fg;
  3025.   if (me)
  3026.   {
  3027.     me->clear();
  3028.     image *im=new image(the_game->ftile_width(),the_game->ftile_height());
  3029.     int th=the_game->ftile_height()/scale,tw=the_game->ftile_width()/scale;
  3030.  
  3031.     for (i=0;i<w*h;i++)
  3032.     {
  3033.       im->clear();      
  3034.       the_game->get_fg(pat[i])->im->put_image(im,0,0);
  3035.       scale_put(im,me->screen,me->x1()+(i%w)*tw,
  3036.         me->y1()+(i/w)*th,tw,th);
  3037.       if (d==pat[i])
  3038.       {
  3039.     find=i;
  3040.     me->screen->rectangle(me->x1()+(i%w)*tw,
  3041.               me->y1()+(i/w)*th,
  3042.               me->x1()+(i%w)*tw+tw-1,
  3043.               me->y1()+(i/w)*th+th-1,eh->bright_color());
  3044.       }
  3045.     }
  3046.     delete im;
  3047.     last_selected=d;
  3048.   }
  3049. }
  3050.  
  3051. #ifdef __POWERPC__
  3052. #pragma global_optimizer reset
  3053. #endif
  3054.  
  3055. void pal_win::handle_event(event &ev) 
  3056. {
  3057.   int d=cur_fg;
  3058.  
  3059.   if (d!=last_selected)  // if so see if we need to hilight any of our tiles.
  3060.   {
  3061.     int i,dr=0;
  3062.     for (i=0;i<w*h;i++) 
  3063.     {
  3064.       if (pat[i]==d || pat[i]==last_selected) 
  3065.         dr=1;
  3066.     }
  3067.     if (dr) draw();
  3068.     last_selected=d;
  3069.   }
  3070.  
  3071.   if (ev.window && ev.window==me)
  3072.   {
  3073.     switch (ev.type)
  3074.     {
  3075.       case EV_MOUSE_BUTTON :
  3076.       {
  3077.         if (ev.mouse_button==1)
  3078.     {      
  3079.       int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
  3080.           sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
  3081.       if (selx>=0 && sely>=0 && selx<w && sely<h)
  3082.       {
  3083.         cur_fg=pat[selx+sely*w];
  3084.         if (dev_cont->forew)      
  3085.           ((tile_picker *)dev_cont->forew->
  3086.            read(DEV_FG_PICKER))->recenter(dev_cont->forew->screen,eh);      
  3087.       }
  3088.     } else if (ev.mouse_button==2)
  3089.     {
  3090.       if (palettes_locked)
  3091.         the_game->show_help(symbol_str("pal_lock"));
  3092.       else
  3093.       {
  3094.         int selx=(last_demo_mx-me->x-me->x1())/(the_game->ftile_width()/scale),
  3095.             sely=(last_demo_my-me->y-me->y1())/(the_game->ftile_height()/scale);
  3096.         if (selx>=0 && sely>=0 && selx<w && sely<h)
  3097.         {
  3098.           pat[selx+sely*w]=cur_fg;
  3099.           draw();
  3100.         }
  3101.       }
  3102.     }
  3103.       } break;
  3104.  
  3105.       case EV_KEY :
  3106.       {
  3107.         switch (ev.key)
  3108.     {
  3109.       case '+' :
  3110.       { if (scale>1)  
  3111.         {
  3112.           close_window();
  3113.           scale--;
  3114.           open_window();
  3115.         }
  3116.       } break;
  3117.       case '-' :
  3118.       { if (scale<the_game->ftile_height()/2) 
  3119.         {
  3120.           close_window();
  3121.           scale++;
  3122.           open_window();
  3123.         }
  3124.       } break;      
  3125.       case JK_LEFT : 
  3126.       {
  3127.         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
  3128.         else if (w>1) resize(-1,0);
  3129.       } break;
  3130.       case JK_RIGHT : 
  3131.       {
  3132.         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
  3133.         else
  3134.           resize(1,0); 
  3135.       } break;
  3136.       case JK_UP : 
  3137.       {
  3138.         if (palettes_locked) the_game->show_help(symbol_str("pal_lock"));
  3139.         else if (h>1) resize(0,-1); 
  3140.       } break;
  3141.       case JK_DOWN : 
  3142.       {
  3143.         if (palettes_locked)         
  3144.           the_game->show_help(symbol_str("pal_lock"));
  3145.         else
  3146.           resize(0,1); 
  3147.       } break;     
  3148.       case JK_ESC : close_window();     break;
  3149.       case ' ' : 
  3150.       {
  3151.         long xs,ys,xx,yy;
  3152.         the_game->ftile_on(me->x,me->y,xs,ys);
  3153.  
  3154.         for (xx=xs;xx<xs+w;xx++)
  3155.         {
  3156.           for (yy=ys;yy<ys+h;yy++)
  3157.           {          
  3158.         if (xx>=0 && yy>=0 && xx<current_level->foreground_width() &&
  3159.             yy<current_level->foreground_height())
  3160.           the_game->put_fg(xx,yy,raise_all ? make_above_tile(pat[xx-xs+(yy-ys)*w]) : pat[xx-xs+(yy-ys)*w] );
  3161.           }
  3162.         }
  3163.       } break;
  3164.       case 't' :
  3165.       {
  3166.         long xs,ys,xx,yy;
  3167.         the_game->ftile_on(me->x,me->y,xs,ys);
  3168.         dev_cont->fg_fill(-1,xs,ys,this);
  3169.       } break;
  3170.  
  3171.     }
  3172.       } break;
  3173.  
  3174.       case EV_CLOSE_WINDOW : close_window(); break;
  3175.     }
  3176.   }
  3177.  
  3178.  
  3179. }
  3180.  
  3181.  
  3182. void pal_win::resize(int xa, int ya)
  3183. {
  3184.   int i,j;
  3185.   unsigned short *npat;
  3186.   if (w+xa<1 || y+ya<1) return ;
  3187.  
  3188.   npat=(unsigned short *)jmalloc(sizeof(unsigned short)*(w+xa)*(h+ya),"resized pal_win");
  3189.   memset(npat,0,sizeof(unsigned short)*(w+xa)*(h+ya));
  3190.   for (i=0;i<(w+xa);i++)
  3191.     for (j=0;j<(h+ya);j++)
  3192.       if (i+j*w<w*h)
  3193.         npat[i+j*(w+xa)]=pat[i+j*w];
  3194.   jfree(pat);
  3195.   w+=xa;
  3196.   h+=ya;
  3197.   pat=npat;
  3198.   last_selected=-1;
  3199.   close_window();
  3200.   open_window();
  3201. }
  3202.  
  3203.  
  3204. void pal_win::save(FILE *fp)
  3205. {
  3206.   if (me)
  3207.   {
  3208.     x=me->x;
  3209.     y=me->y;
  3210.   }
  3211.  
  3212.   fprintf(fp,"(add_palette \"%s\" %d %d %d %d %d ",name,w,h,x,y,scale);
  3213.   int i;
  3214.   for (i=0;i<w*h;i++)
  3215.     fprintf(fp,"%d ",pat[i]&0x7fff);
  3216.   fprintf(fp,")\n");
  3217.  
  3218. }
  3219.  
  3220. FILE *open_FILE(char *filename, char *mode);
  3221.  
  3222. void dev_controll::save()
  3223. {
  3224.   FILE *fp=open_FILE("edit.lsp","w");
  3225.   if (!fp) 
  3226.     the_game->show_help(symbol_str("no_edit.lsp"));
  3227.   else
  3228.   {
  3229.     fprintf(fp,"(set_zoom %d)\n",the_game->zoom);
  3230.    
  3231.     int i;
  3232.     for (i=0;i<total_pals;i++)
  3233.     {
  3234.       pal_wins[i]->save(fp);
  3235.     }
  3236.     fprintf(fp,"\n");
  3237.     fclose(fp);
  3238.   }
  3239.  
  3240. }
  3241.  
  3242. int dev_controll::is_pal_win(jwindow *win)
  3243. {
  3244.   int i;
  3245.   for (i=0;i<total_pals;i++)
  3246.     if (win==pal_wins[i]->me) return 1;
  3247.   return 0;
  3248. }
  3249.  
  3250.  
  3251. class fill_rec
  3252. {
  3253. public :
  3254.   short x,y;
  3255.   fill_rec *last;
  3256.   fill_rec(short X, short Y, fill_rec *Last)
  3257.   { x=X; y=Y; last=Last; }
  3258. } ;
  3259.  
  3260. static int get_color(int color, int x, int y, pal_win *p)
  3261. {
  3262.   if (p)  
  3263.   {
  3264.     while (x<0) x+=p->width();
  3265.     while (y<0) y+=p->height();
  3266.     return p->get_pat(x%p->width(),y%p->height());
  3267.   }
  3268.   else return color;
  3269. }
  3270.  
  3271. void dev_controll::fg_fill(int color, int x, int y, pal_win *p)
  3272. {
  3273.   unsigned short *sl,*above,*below;
  3274.   fill_rec *recs=NULL,*r;
  3275.   unsigned short fcolor;
  3276.   sl=current_level->get_fgline(y);
  3277.   fcolor=fgvalue(sl[x]);
  3278.   int startx=x,starty=y;
  3279.   if (fcolor==color) return ;
  3280.   do
  3281.   {
  3282.     if (recs)
  3283.     { r=recs;
  3284.       recs=recs->last;
  3285.       x=r->x; y=r->y;
  3286.       delete r;
  3287.     }
  3288.     sl=current_level->get_fgline(y);
  3289.     if (fgvalue(sl[x])==fcolor)
  3290.     {
  3291.       while (x>0 && fgvalue(sl[x])==fcolor) x--;
  3292.       if (fgvalue(sl[x])!=fgvalue(fcolor) && x<current_level->foreground_width()-1) x++;
  3293.       if (y>0)
  3294.       {
  3295.         above=current_level->get_fgline(y-1);
  3296.         if (fgvalue(above[x])==fcolor)
  3297.         { r=new fill_rec(x,y-1,recs);
  3298.           recs=r;  
  3299.         }
  3300.       }
  3301.       if (y<current_level->foreground_height()-1)
  3302.       {
  3303.         above=current_level->get_fgline(y+1);
  3304.         if (above[x]==fcolor)
  3305.         { r=new fill_rec(x,y+1,recs);
  3306.           recs=r;
  3307.         }
  3308.       }
  3309.  
  3310.  
  3311.  
  3312.       do
  3313.       {
  3314.         sl[x]=get_color(color,x-startx,y-starty,p);
  3315.         if (y>0)
  3316.         { above=current_level->get_fgline(y-1);
  3317.           if (x>0 && fgvalue(above[x-1])!=fgvalue(fcolor) && fgvalue(above[x])==fgvalue(fcolor))
  3318.           { r=new fill_rec(x,y-1,recs);
  3319.             recs=r;  
  3320.           }
  3321.         }
  3322.         if (y<current_level->foreground_height()-1)
  3323.         { below=current_level->get_fgline(y+1);
  3324.           if (x>0 && fgvalue(below[x-1])!=fgvalue(fcolor) && fgvalue(below[x])==fgvalue(fcolor))
  3325.           { r=new fill_rec(x,y+1,recs);
  3326.             recs=r;  
  3327.           }
  3328.         }
  3329.         x++;
  3330.       } while (fgvalue(sl[x])==fgvalue(fcolor) && x<current_level->foreground_width());
  3331.       x--;
  3332.       if (y>0)
  3333.       {
  3334.         above=current_level->get_fgline(y-1);
  3335.         if (fgvalue(above[x])==fgvalue(fcolor))
  3336.         { r=new fill_rec(x,y-1,recs);
  3337.           recs=r;
  3338.         }
  3339.       }
  3340.       if (y<current_level->foreground_height()-1)
  3341.       {
  3342.         above=current_level->get_fgline(y+1);
  3343.         if (fgvalue(above[x])==fgvalue(fcolor))
  3344.         { r=new fill_rec(x,y+1,recs);
  3345.           recs=r;
  3346.         }
  3347.       }
  3348.     }
  3349.   } while (recs);
  3350.   the_game->need_refresh();
  3351. }
  3352.  
  3353. int get_char_mem(int type, int print)
  3354. {
  3355.   int t=0;
  3356.   for (int j=0;j<MAX_STATE;j++)
  3357.   {
  3358.     if (figures[type]->has_sequence((character_state)j))
  3359.     {
  3360.       int s=figures[type]->get_sequence((character_state)j)->size();
  3361.       if (print)
  3362.         dprintf("(%s=%d)",state_names[j],s);
  3363.       t+=s;
  3364.     }
  3365.   }
  3366.   if (print)
  3367.     dprintf("\ntotal=%d\n",t);      
  3368.   return t;
  3369. }
  3370.  
  3371. void dev_controll::show_char_mem(char *name)
  3372. {
  3373.   int find=-1;
  3374.   for (int i=0;i<total_objects;i++)
  3375.   {
  3376.     if (!strcmp(name,object_names[i]))
  3377.       find=i;
  3378.   }
  3379.   if (find<0)
  3380.     dprintf("No character '%s' defined\n",name);
  3381.   else  
  3382.     get_char_mem(find,1);
  3383.   
  3384. }
  3385.  
  3386. void dev_controll::show_mem()
  3387. {
  3388.   int t=0,s=0;
  3389.   int i=0;
  3390.   for (;i<nforetiles;i++)
  3391.   {
  3392.     if (foretiles[i]>=0)
  3393.     {
  3394.       if (cash.loaded(foretiles[i]))
  3395.       {
  3396.     t++;      
  3397.     s+=cash.foret(foretiles[i])->size();
  3398.       }
  3399.     }
  3400.   }
  3401.   dprintf("%d loaded foretiles=%d bytes\n",t,s);
  3402.  
  3403.   t=0; s=0;
  3404.   for (i=0;i<nbacktiles;i++)
  3405.   {
  3406.     if (backtiles[i]>=0)
  3407.     {
  3408.       if (cash.loaded(foretiles[i]))
  3409.       {
  3410.     t++;
  3411.     s+=cash.backt(backtiles[i])->size();
  3412.       }
  3413.     }
  3414.   }
  3415.   dprintf("%d loaded backtiles=%d bytes\n",t,s);
  3416.   
  3417.   t=0; s=0;
  3418.   for (i=0;i<total_objects;i++)
  3419.   {
  3420.     t++;
  3421.     s+=get_char_mem(i,0);
  3422.   }
  3423.   dprintf("%d character=%d bytes\n",t,s);
  3424.  
  3425. }
  3426.  
  3427.  
  3428.  
  3429. void dev_cleanup()
  3430. {
  3431.   if (start_edit)  
  3432.     prop->save("defaults.prp");
  3433.   delete prop;
  3434.   if (listable_objs)
  3435.   {
  3436.     jfree(listable_objs);
  3437.     listable_objs=NULL;
  3438.   }
  3439.   crc_man.clean_up();
  3440.  
  3441. }
  3442.  
  3443.  
  3444.  
  3445. struct pmi
  3446. {
  3447.   char *name;
  3448.   int id;
  3449.   char *on_off;
  3450.   int key;
  3451. } ;
  3452.  
  3453.  
  3454. static pmi fm[]={
  3455.           {"menu1_load",         ID_LEVEL_LOAD,NULL,-1},
  3456.       {NULL,0,NULL,-1},
  3457.       {"menu1_save",     ID_LEVEL_SAVE,NULL,-1},
  3458.       {"menu1_saveas",      ID_LEVEL_SAVEAS,NULL,-1},
  3459.       {"menu1_savegame",          ID_GAME_SAVE,NULL,-1},
  3460.       {"menu1_new",          ID_LEVEL_NEW,NULL,-1},
  3461.       {"menu1_resize",         ID_LEVEL_RESIZE,NULL,-1},
  3462.       {NULL,0,NULL,-1},
  3463.       {"menu1_suspend",ID_SUSPEND,NULL,-1},
  3464.       {"menu1_toggle",ID_PLAY_MODE,NULL,-1},
  3465.       {NULL,0,NULL,-1},
  3466.       {"menu1_savepal",ID_EDIT_SAVE,NULL,-1},
  3467. //      {"menu1_startc",ID_CACHE_PROFILE,NULL,-1},
  3468. //      {"menu1_endc",ID_CACHE_PROFILE_END,NULL,-1},
  3469.       {NULL,0,NULL,-1},     
  3470.       {"menu1_quit",      ID_QUIT,NULL,-1},
  3471.       {NULL,-1,NULL,-1}
  3472.     };
  3473.  
  3474.  
  3475. static pmi em[]={
  3476.   {"menu2_light",               ID_TOGGLE_LIGHT,NULL,-1},
  3477.   {"menu2_scroll",            ID_SET_SCROLL,NULL,-1},
  3478.   {"menu2_center",       ID_CENTER_PLAYER,NULL,-1},
  3479.   {"menu2_addpal",                ID_ADD_PALETTE,NULL,-1},
  3480.   {"menu2_delay",          ID_TOGGLE_DELAY,NULL,-1},
  3481.  
  3482.   {"menu2_god",                   ID_GOD_MODE,NULL,-1},
  3483.   {"menu2_clear",          ID_CLEAR_WEAPONS,NULL,-1},
  3484.   {"menu2_mscroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
  3485.   {"menu2_lock",       ID_LOCK_PALETTES,&palettes_locked,-1},
  3486.   {"menu2_raise",       ID_RAISE_ALL,&raise_all,-1},
  3487.   {"menu2_names",        ID_TOGGLE_NAMES,&show_names,-1},
  3488.  
  3489.   {NULL,0,NULL,-1},
  3490.   {"menu2_map",      ID_TOGGLE_MAP,NULL,-1},
  3491. //  {"Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
  3492.   {"menu2_view",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1}, 
  3493. //  {"Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
  3494.   {"menu2_alight",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
  3495.   {"menu2_fps",         ID_SHOW_FPS,          &fps_on,-1},
  3496. //  {NULL,0,NULL,-1},
  3497. //  {"Record demo",                ID_RECORD_DEMO,NULL,-1},
  3498. //  {"Play demo",                  ID_PLAY_DEMO,NULL,-1},
  3499.   {NULL,-1,NULL,-1}
  3500. };
  3501.  
  3502.  
  3503.  
  3504. // Window Menus
  3505. static pmi wm[]={
  3506.           {"menu3_fore",    ID_WIN_FORE,    &forew_on,-1},
  3507.           {"menu3_back",    ID_WIN_BACK,    &backw_on,-1},
  3508.           {"menu3_layers",    ID_WIN_LAYERS,  &show_menu_on,-1},
  3509.       {"menu3_light",    ID_WIN_LIGHTING,&ledit_on,-1},
  3510.       {"menu3_pal",    ID_WIN_PALETTES,&pmenu_on,-1},
  3511.       {"menu3_objs",    ID_WIN_OBJECTS, &omenu_on,-1},
  3512. //      {"menu3_console",    ID_WIN_CONSOLE, &commandw_on,-1},
  3513.       {"menu3_toolbar",    ID_WIN_TOOLBAR, &tbw_on,-1},
  3514. //      {"Search      (s)",    ID_SEARCH,      &searchw_on,-1},
  3515.       {"menu3_prof",    ID_PROFILE,     &profile_on,-1},
  3516.       {"menu3_save",     ID_SAVE_WINDOWS,NULL,-1},
  3517.       {NULL,-1,NULL,-1}
  3518.     };
  3519.  
  3520.  
  3521.  
  3522. /*
  3523. static pmi fm[]={
  3524.           {"Load Level",         ID_LEVEL_LOAD,NULL,-1},
  3525.       {NULL,0,NULL,-1},
  3526.       {"Save Level (S)",     ID_LEVEL_SAVE,NULL,-1},
  3527.       {"Save level as",      ID_LEVEL_SAVEAS,NULL,-1},
  3528.       {"Save game",          ID_GAME_SAVE,NULL,-1},
  3529.       {"New level",          ID_LEVEL_NEW,NULL,-1},
  3530.       {"Resize map",         ID_LEVEL_RESIZE,NULL,-1},
  3531.       {NULL,0,NULL,-1},
  3532.       {"Suspend non-players",ID_SUSPEND,NULL,-1},
  3533.       {"Play mode toggle (TAB)",ID_PLAY_MODE,NULL,-1},
  3534.       {NULL,0,NULL,-1},
  3535.       {"Save Palettes         ",ID_EDIT_SAVE,NULL,-1},
  3536.       {"Start cache profile   ",ID_CACHE_PROFILE,NULL,-1},
  3537.       {"End cache profile     ",ID_CACHE_PROFILE_END,NULL,-1},
  3538.       {NULL,0,NULL,-1},     
  3539.       {"Quit      (Q)",      ID_QUIT,NULL,-1},
  3540.       {NULL,-1,NULL,-1}
  3541.     };
  3542.  
  3543.  
  3544. static pmi em[]={
  3545.   {"Toggle light",               ID_TOGGLE_LIGHT,NULL,-1},
  3546.   {"Set scroll rate",            ID_SET_SCROLL,NULL,-1},
  3547.   {"Center on player   (c)",       ID_CENTER_PLAYER,NULL,-1},
  3548.   {"Add palette",                ID_ADD_PALETTE,NULL,-1},
  3549.   {"Toggle Delays      (D)",          ID_TOGGLE_DELAY,NULL,-1},
  3550.  
  3551.   {"God mode",                   ID_GOD_MODE,NULL,-1},
  3552.   {"Clear weapons (z)",          ID_CLEAR_WEAPONS,NULL,-1},
  3553.   {"Mouse scroll",               ID_MOUSE_SCROLL,&mouse_scrolling,-1},
  3554.   {"Lock palette windows",       ID_LOCK_PALETTES,&palettes_locked,-1},
  3555.   {"Raise all foreground",       ID_RAISE_ALL,&raise_all,-1},
  3556.   {"Toggle object names",        ID_TOGGLE_NAMES,&show_names,-1},
  3557.  
  3558.   {NULL,0,NULL,-1},
  3559.   {"Toggle map        (m)",      ID_TOGGLE_MAP,NULL,-1},
  3560. //  {"Shrink to 320x200 (F10)",    ID_SMALL_MODE,NULL,-1},
  3561.   {"Disable view shifts",        ID_DISABLE_VIEW_SHIFT,&view_shift_disabled,-1}, 
  3562. //  {"Ultra Smooth draw (U)",      ID_INTERPOLATE_DRAW,  &interpolate_draw,'U'},
  3563.   {"Disable Autolight (A)",      ID_DISABLE_AUTOLIGHT, &disable_autolight,'A'},
  3564.   {"Show FPS/Obj count",         ID_SHOW_FPS,          &fps_on,-1},
  3565. //  {NULL,0,NULL,-1},
  3566. //  {"Record demo",                ID_RECORD_DEMO,NULL,-1},
  3567. //  {"Play demo",                  ID_PLAY_DEMO,NULL,-1},
  3568.   {NULL,-1,NULL,-1}
  3569. };
  3570.  
  3571.  
  3572.  
  3573. // Window Menus
  3574. static pmi wm[]={
  3575.           {"Foreground  (f)",    ID_WIN_FORE,    &forew_on,-1},
  3576.           {"Background  (b)",    ID_WIN_BACK,    &backw_on,-1},
  3577.           {"Draw layers (L)",    ID_WIN_LAYERS,  &show_menu_on,-1},
  3578.       {"Lighting    (l)",    ID_WIN_LIGHTING,&ledit_on,-1},
  3579.       {"Palettes    (p)",    ID_WIN_PALETTES,&pmenu_on,-1},
  3580.       {"Objects     (o)",    ID_WIN_OBJECTS, &omenu_on,-1},
  3581.       {"Console     (/)",    ID_WIN_CONSOLE, &commandw_on,-1},
  3582.       {"Tool Bar    (a)",    ID_WIN_TOOLBAR, &tbw_on,-1},
  3583. //      {"Search      (s)",    ID_SEARCH,      &searchw_on,-1},
  3584.       {"Profile     (P)",    ID_PROFILE,     &profile_on,-1},
  3585.       {"Save positions",     ID_SAVE_WINDOWS,NULL,-1},
  3586.       {NULL,-1,NULL,-1}
  3587.     };
  3588.  
  3589. */
  3590.     
  3591. static pmenu_item *i_recurse(pmi *first)
  3592. {
  3593.   if (first->id==-1)
  3594.     return NULL;
  3595.   else  
  3596.     return new pmenu_item(first->id,first->name ? symbol_str(first->name) : 0,first->on_off,first->key,i_recurse(first+1));
  3597. }
  3598.     
  3599. static pmenu *make_menu(int x, int y)
  3600. {
  3601.   return new pmenu(x,y,
  3602.          new pmenu_item(symbol_str("file_top"),new psub_menu(i_recurse(fm),NULL),
  3603.      new pmenu_item(symbol_str("edit_top"),new psub_menu(i_recurse(em),NULL),
  3604.      new pmenu_item(symbol_str("window_top"),new psub_menu(i_recurse(wm),NULL),NULL))),screen,eh);
  3605. }
  3606.  
  3607.  
  3608.  
  3609. void toggle_edit_mode()
  3610. {
  3611.   dev=dev^EDIT_MODE;
  3612.   if (dev&EDIT_MODE)
  3613.   {
  3614.     eh->set_mouse_shape(cash.img(c_normal)->copy(),1,1);
  3615.     pal->load();
  3616.   }
  3617.   else
  3618.   {
  3619.     if (dev&MAP_MODE) dev-=MAP_MODE;                        // no map mode while playing!
  3620.     eh->set_mouse_shape(cash.img(c_target)->copy(),8,8);
  3621.   }
  3622.   if ((dev&EDIT_MODE) && !dev_menu)
  3623.   {
  3624.     dev_menu=make_menu(0,yres-eh->font()->height()-5);    
  3625.   }
  3626.   else if (!(dev&EDIT_MODE) && dev_menu)
  3627.   {
  3628.     delete dev_menu;
  3629.     dev_menu=NULL;
  3630.   } 
  3631. }
  3632.  
  3633.  
  3634. int dev_controll::ok_to_scroll()
  3635. {
  3636.   if (state==DEV_MOVE_LIGHT || state==DEV_MOVE_OBJECT || mouse_scrolling) return 1;
  3637.   else return 0;
  3638. }
  3639.  
  3640. dev_controll::~dev_controll()
  3641. {
  3642.   for (int i=0;i<total_pals;i++)
  3643.     delete pal_wins[i];
  3644.   if (total_pals)
  3645.     jfree(pal_wins);
  3646. }
  3647.  
  3648.  
  3649.  
  3650. pal_win::~pal_win()
  3651. {
  3652.   jfree(pat);
  3653.   jfree(name);
  3654. }
  3655.